start_fake_mint.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. //! Binary for starting a fake mint for testing
  2. //!
  3. //! This binary provides a programmatic way to start a fake mint instance for testing purposes:
  4. //! 1. Sets up a fake mint instance using the cdk-mintd library
  5. //! 2. Configures the mint with fake wallet backend for testing Lightning Network interactions
  6. //! 3. Waits for the mint to be ready and responsive
  7. //! 4. Keeps it running until interrupted (Ctrl+C)
  8. //! 5. Gracefully shuts down on receiving shutdown signal
  9. //!
  10. //! This approach offers better control and integration compared to external scripts,
  11. //! making it easier to run integration tests with consistent configuration.
  12. use std::path::Path;
  13. use std::sync::Arc;
  14. use anyhow::Result;
  15. use cdk::nuts::CurrencyUnit;
  16. use cdk_integration_tests::cli::CommonArgs;
  17. use cdk_integration_tests::shared;
  18. use clap::Parser;
  19. use tokio::sync::Notify;
  20. use tokio_util::sync::CancellationToken;
  21. #[derive(Parser)]
  22. #[command(name = "start-fake-mint")]
  23. #[command(about = "Start a fake mint for testing", long_about = None)]
  24. struct Args {
  25. #[command(flatten)]
  26. common: CommonArgs,
  27. /// Database type (sqlite)
  28. database_type: String,
  29. /// Working directory path
  30. work_dir: String,
  31. /// Port to listen on (default: 8086)
  32. #[arg(default_value_t = 8086)]
  33. port: u16,
  34. /// Use external signatory
  35. #[arg(long, default_value_t = false)]
  36. external_signatory: bool,
  37. }
  38. /// Start a fake mint using the library
  39. async fn start_fake_mint(
  40. temp_dir: &Path,
  41. port: u16,
  42. database: &str,
  43. shutdown: Arc<Notify>,
  44. external_signatory: bool,
  45. ) -> Result<tokio::task::JoinHandle<()>> {
  46. let signatory_config = if external_signatory {
  47. println!("Configuring external signatory");
  48. Some((
  49. "https://127.0.0.1:15060".to_string(), // Default signatory URL
  50. temp_dir.to_string_lossy().to_string(), // Certs directory as string
  51. ))
  52. } else {
  53. None
  54. };
  55. let mnemonic = if external_signatory {
  56. None
  57. } else {
  58. Some(
  59. "eye survey guilt napkin crystal cup whisper salt luggage manage unveil loyal"
  60. .to_string(),
  61. )
  62. };
  63. let fake_wallet_config = Some(cdk_mintd::config::FakeWallet {
  64. supported_units: vec![CurrencyUnit::Sat, CurrencyUnit::Usd],
  65. fee_percent: 0.0,
  66. reserve_fee_min: 1.into(),
  67. min_delay_time: 1,
  68. max_delay_time: 3,
  69. });
  70. // Create settings struct for fake mint using shared function
  71. let settings = shared::create_fake_wallet_settings(
  72. port,
  73. database,
  74. mnemonic,
  75. signatory_config,
  76. fake_wallet_config,
  77. );
  78. println!("Starting fake mintd on port {port}");
  79. let temp_dir = temp_dir.to_path_buf();
  80. let shutdown_clone = shutdown.clone();
  81. // Run the mint in a separate task
  82. let handle = tokio::spawn(async move {
  83. // Create a future that resolves when the shutdown signal is received
  84. let shutdown_future = async move {
  85. shutdown_clone.notified().await;
  86. println!("Fake mint shutdown signal received");
  87. };
  88. match cdk_mintd::run_mintd_with_shutdown(
  89. &temp_dir,
  90. &settings,
  91. shutdown_future,
  92. None,
  93. None,
  94. vec![],
  95. )
  96. .await
  97. {
  98. Ok(_) => println!("Fake mint exited normally"),
  99. Err(e) => eprintln!("Fake mint exited with error: {e}"),
  100. }
  101. });
  102. Ok(handle)
  103. }
  104. #[tokio::main]
  105. async fn main() -> Result<()> {
  106. let args = Args::parse();
  107. // Initialize logging based on CLI arguments
  108. shared::setup_logging(&args.common);
  109. let temp_dir = shared::init_working_directory(&args.work_dir)?;
  110. // Write environment variables to a .env file in the temp_dir BEFORE starting the mint
  111. let mint_url = format!("http://127.0.0.1:{}", args.port);
  112. let itests_dir = temp_dir.display().to_string();
  113. let env_vars: Vec<(&str, &str)> = vec![
  114. ("CDK_TEST_MINT_URL", &mint_url),
  115. ("CDK_ITESTS_DIR", &itests_dir),
  116. ];
  117. shared::write_env_file(&temp_dir, &env_vars)?;
  118. // Start fake mint
  119. let shutdown = shared::create_shutdown_handler();
  120. let shutdown_clone = shutdown.clone();
  121. let handle = start_fake_mint(
  122. &temp_dir,
  123. args.port,
  124. &args.database_type,
  125. shutdown_clone,
  126. args.external_signatory,
  127. )
  128. .await?;
  129. let cancel_token = Arc::new(CancellationToken::new());
  130. // Wait for fake mint to be ready
  131. if let Err(e) = shared::wait_for_mint_ready_with_shutdown(args.port, 100, cancel_token).await {
  132. eprintln!("Error waiting for fake mint: {e}");
  133. return Err(e);
  134. }
  135. shared::display_mint_info(args.port, &temp_dir, &args.database_type);
  136. println!();
  137. println!(
  138. "Environment variables written to: {}/.env",
  139. temp_dir.display()
  140. );
  141. println!("You can source these variables with:");
  142. println!(" source {}/.env", temp_dir.display());
  143. println!();
  144. println!("Environment variables set:");
  145. println!(" CDK_TEST_MINT_URL=http://127.0.0.1:{}", args.port);
  146. println!(" CDK_ITESTS_DIR={}", temp_dir.display());
  147. println!();
  148. println!("You can now run integration tests with:");
  149. println!(" cargo test -p cdk-integration-tests --test fake_wallet");
  150. println!(" cargo test -p cdk-integration-tests --test happy_path_mint_wallet");
  151. println!(" etc.");
  152. println!();
  153. println!("Press Ctrl+C to stop the mint...");
  154. // Wait for Ctrl+C signal
  155. shared::wait_for_shutdown_signal(shutdown).await;
  156. println!("\nReceived Ctrl+C, shutting down mint...");
  157. // Wait for mint to finish gracefully
  158. if let Err(e) = handle.await {
  159. eprintln!("Error waiting for mint to shut down: {e}");
  160. }
  161. println!("Mint shut down successfully");
  162. Ok(())
  163. }