lib.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. use std::str::FromStr;
  2. use std::sync::Arc;
  3. use anyhow::{bail, Result};
  4. use cdk::amount::{Amount, SplitTarget};
  5. use cdk::dhke::construct_proofs;
  6. use cdk::mint_url::MintUrl;
  7. use cdk::nuts::nut00::ProofsMethods;
  8. use cdk::nuts::nut17::Params;
  9. use cdk::nuts::{
  10. CurrencyUnit, Id, KeySet, MintBolt11Request, MintQuoteBolt11Request, MintQuoteState,
  11. NotificationPayload, PreMintSecrets, Proofs, State,
  12. };
  13. use cdk::wallet::client::{HttpClient, MintConnector};
  14. use cdk::wallet::subscription::SubscriptionManager;
  15. use cdk::wallet::WalletSubscription;
  16. use cdk::Wallet;
  17. pub mod init_fake_wallet;
  18. pub mod init_mint;
  19. pub mod init_pure_tests;
  20. pub mod init_regtest;
  21. pub async fn wallet_mint(
  22. wallet: Arc<Wallet>,
  23. amount: Amount,
  24. split_target: SplitTarget,
  25. description: Option<String>,
  26. ) -> Result<()> {
  27. let quote = wallet.mint_quote(amount, description).await?;
  28. let mut subscription = wallet
  29. .subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
  30. .id
  31. .clone()]))
  32. .await;
  33. while let Some(msg) = subscription.recv().await {
  34. if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
  35. if response.state == MintQuoteState::Paid {
  36. break;
  37. }
  38. }
  39. }
  40. let proofs = wallet.mint(&quote.id, split_target, None).await?;
  41. let receive_amount = proofs.total_amount()?;
  42. println!("Minted: {}", receive_amount);
  43. Ok(())
  44. }
  45. pub async fn mint_proofs(
  46. mint_url: &str,
  47. amount: Amount,
  48. keyset_id: Id,
  49. mint_keys: &KeySet,
  50. description: Option<String>,
  51. ) -> anyhow::Result<Proofs> {
  52. println!("Minting for ecash");
  53. println!();
  54. let wallet_client = HttpClient::new(MintUrl::from_str(mint_url)?);
  55. let request = MintQuoteBolt11Request {
  56. amount,
  57. unit: CurrencyUnit::Sat,
  58. description,
  59. pubkey: None,
  60. };
  61. let mint_quote = wallet_client.post_mint_quote(request).await?;
  62. println!("Please pay: {}", mint_quote.request);
  63. let subscription_client = SubscriptionManager::new(Arc::new(wallet_client.clone()));
  64. let mut subscription = subscription_client
  65. .subscribe(
  66. mint_url.parse()?,
  67. Params {
  68. filters: vec![mint_quote.quote.clone()],
  69. kind: cdk::nuts::nut17::Kind::Bolt11MintQuote,
  70. id: "sub".into(),
  71. },
  72. )
  73. .await;
  74. while let Some(msg) = subscription.recv().await {
  75. if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
  76. if response.state == MintQuoteState::Paid {
  77. break;
  78. }
  79. }
  80. }
  81. let premint_secrets = PreMintSecrets::random(keyset_id, amount, &SplitTarget::default())?;
  82. let request = MintBolt11Request {
  83. quote: mint_quote.quote,
  84. outputs: premint_secrets.blinded_messages(),
  85. signature: None,
  86. };
  87. let mint_response = wallet_client.post_mint(request).await?;
  88. let pre_swap_proofs = construct_proofs(
  89. mint_response.signatures,
  90. premint_secrets.rs(),
  91. premint_secrets.secrets(),
  92. &mint_keys.clone().keys,
  93. )?;
  94. Ok(pre_swap_proofs)
  95. }
  96. // Get all pending from wallet and attempt to swap
  97. // Will panic if there are no pending
  98. // Will return Ok if swap fails as expected
  99. pub async fn attempt_to_swap_pending(wallet: &Wallet) -> Result<()> {
  100. let pending = wallet
  101. .localstore
  102. .get_proofs(None, None, Some(vec![State::Pending]), None)
  103. .await?;
  104. assert!(!pending.is_empty());
  105. let swap = wallet
  106. .swap(
  107. None,
  108. SplitTarget::None,
  109. pending.into_iter().map(|p| p.proof).collect(),
  110. None,
  111. false,
  112. )
  113. .await;
  114. match swap {
  115. Ok(_swap) => {
  116. bail!("These proofs should be pending")
  117. }
  118. Err(err) => match err {
  119. cdk::error::Error::TokenPending => (),
  120. _ => {
  121. println!("{:?}", err);
  122. bail!("Wrong error")
  123. }
  124. },
  125. }
  126. Ok(())
  127. }
  128. // Keep polling the state of the mint quote id until it's paid
  129. pub async fn wait_for_mint_to_be_paid(wallet: &Wallet, mint_quote_id: &str) -> Result<()> {
  130. let mut subscription = wallet
  131. .subscribe(WalletSubscription::Bolt11MintQuoteState(vec![
  132. mint_quote_id.to_owned(),
  133. ]))
  134. .await;
  135. while let Some(msg) = subscription.recv().await {
  136. if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
  137. if response.state == MintQuoteState::Paid {
  138. break;
  139. }
  140. }
  141. }
  142. Ok(())
  143. }