lib.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use std::sync::Arc;
  2. use anyhow::{anyhow, bail, Result};
  3. use cdk::amount::{Amount, SplitTarget};
  4. use cdk::nuts::{MintQuoteState, NotificationPayload, State};
  5. use cdk::wallet::WalletSubscription;
  6. use cdk::Wallet;
  7. use tokio::time::{sleep, timeout, Duration};
  8. pub mod init_auth_mint;
  9. pub mod init_pure_tests;
  10. pub mod init_regtest;
  11. pub async fn fund_wallet(wallet: Arc<Wallet>, amount: Amount) {
  12. let quote = wallet
  13. .mint_quote(amount, None)
  14. .await
  15. .expect("Could not get mint quote");
  16. wait_for_mint_to_be_paid(&wallet, &quote.id, 60)
  17. .await
  18. .expect("Waiting for mint failed");
  19. let _proofs = wallet
  20. .mint(&quote.id, SplitTarget::default(), None)
  21. .await
  22. .expect("Could not mint");
  23. }
  24. // Get all pending from wallet and attempt to swap
  25. // Will panic if there are no pending
  26. // Will return Ok if swap fails as expected
  27. pub async fn attempt_to_swap_pending(wallet: &Wallet) -> Result<()> {
  28. let pending = wallet
  29. .localstore
  30. .get_proofs(None, None, Some(vec![State::Pending]), None)
  31. .await?;
  32. assert!(!pending.is_empty());
  33. let swap = wallet
  34. .swap(
  35. None,
  36. SplitTarget::None,
  37. pending.into_iter().map(|p| p.proof).collect(),
  38. None,
  39. false,
  40. )
  41. .await;
  42. match swap {
  43. Ok(_swap) => {
  44. bail!("These proofs should be pending")
  45. }
  46. Err(err) => match err {
  47. cdk::error::Error::TokenPending => (),
  48. _ => {
  49. println!("{:?}", err);
  50. bail!("Wrong error")
  51. }
  52. },
  53. }
  54. Ok(())
  55. }
  56. pub async fn wait_for_mint_to_be_paid(
  57. wallet: &Wallet,
  58. mint_quote_id: &str,
  59. timeout_secs: u64,
  60. ) -> Result<()> {
  61. let mut subscription = wallet
  62. .subscribe(WalletSubscription::Bolt11MintQuoteState(vec![
  63. mint_quote_id.to_owned(),
  64. ]))
  65. .await;
  66. // Create the timeout future
  67. let wait_future = async {
  68. while let Some(msg) = subscription.recv().await {
  69. if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
  70. if response.state == MintQuoteState::Paid {
  71. return Ok(());
  72. }
  73. }
  74. }
  75. Err(anyhow!("Subscription ended without quote being paid"))
  76. };
  77. let timeout_future = timeout(Duration::from_secs(timeout_secs), wait_future);
  78. let check_interval = Duration::from_secs(5);
  79. let periodic_task = async {
  80. loop {
  81. match wallet.mint_quote_state(mint_quote_id).await {
  82. Ok(result) => {
  83. if result.state == MintQuoteState::Paid {
  84. tracing::info!("mint quote paid via poll");
  85. return Ok(());
  86. }
  87. }
  88. Err(e) => {
  89. tracing::error!("Could not check mint quote status: {:?}", e);
  90. }
  91. }
  92. sleep(check_interval).await;
  93. }
  94. };
  95. tokio::select! {
  96. result = timeout_future => {
  97. match result {
  98. Ok(payment_result) => payment_result,
  99. Err(_) => Err(anyhow!("Timeout waiting for mint quote to be paid")),
  100. }
  101. }
  102. result = periodic_task => {
  103. result // Now propagates the result from periodic checks
  104. }
  105. }
  106. }