mint.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. use std::str::FromStr;
  2. use anyhow::{anyhow, Result};
  3. use cdk::amount::SplitTarget;
  4. use cdk::mint_url::MintUrl;
  5. use cdk::nuts::nut00::ProofsMethods;
  6. use cdk::nuts::PaymentMethod;
  7. use cdk::wallet::MultiMintWallet;
  8. use cdk::{Amount, StreamExt};
  9. use cdk_common::nut00::KnownMethod;
  10. use clap::Args;
  11. use serde::{Deserialize, Serialize};
  12. use crate::utils::get_or_create_wallet;
  13. #[derive(Args, Serialize, Deserialize)]
  14. pub struct MintSubCommand {
  15. /// Mint url
  16. mint_url: MintUrl,
  17. /// Amount
  18. amount: Option<u64>,
  19. /// Quote description
  20. #[serde(skip_serializing_if = "Option::is_none")]
  21. description: Option<String>,
  22. /// Quote Id
  23. #[arg(short, long)]
  24. quote_id: Option<String>,
  25. /// Payment method
  26. #[arg(long, default_value = "bolt11")]
  27. method: String,
  28. /// Expiry
  29. #[arg(short, long)]
  30. expiry: Option<u64>,
  31. /// Expiry
  32. #[arg(short, long)]
  33. single_use: Option<bool>,
  34. /// Wait duration in seconds for mint quote polling
  35. #[arg(long, default_value = "30")]
  36. wait_duration: u64,
  37. }
  38. pub async fn mint(
  39. multi_mint_wallet: &MultiMintWallet,
  40. sub_command_args: &MintSubCommand,
  41. ) -> Result<()> {
  42. let mint_url = sub_command_args.mint_url.clone();
  43. let description: Option<String> = sub_command_args.description.clone();
  44. let wallet = get_or_create_wallet(multi_mint_wallet, &mint_url).await?;
  45. let payment_method = PaymentMethod::from_str(&sub_command_args.method)?;
  46. let quote = match &sub_command_args.quote_id {
  47. None => match payment_method {
  48. PaymentMethod::Known(KnownMethod::Bolt11) => {
  49. let amount = sub_command_args
  50. .amount
  51. .ok_or(anyhow!("Amount must be defined"))?;
  52. let quote = wallet.mint_quote(Amount::from(amount), description).await?;
  53. println!("Quote: {quote:#?}");
  54. println!("Please pay: {}", quote.request);
  55. quote
  56. }
  57. PaymentMethod::Known(KnownMethod::Bolt12) => {
  58. let amount = sub_command_args.amount;
  59. println!("{:?}", sub_command_args.single_use);
  60. let quote = wallet
  61. .mint_bolt12_quote(amount.map(|a| a.into()), description)
  62. .await?;
  63. println!("Quote: {quote:#?}");
  64. println!("Please pay: {}", quote.request);
  65. quote
  66. }
  67. _ => {
  68. let amount = sub_command_args.amount;
  69. println!("{:?}", sub_command_args.single_use);
  70. let quote = wallet
  71. .mint_quote_unified(
  72. amount.map(|a| a.into()),
  73. payment_method.clone(),
  74. None,
  75. None,
  76. )
  77. .await?;
  78. println!("Quote: {quote:#?}");
  79. println!("Please pay: {}", quote.request);
  80. quote
  81. }
  82. },
  83. Some(quote_id) => wallet
  84. .localstore
  85. .get_mint_quote(quote_id)
  86. .await?
  87. .ok_or(anyhow!("Unknown quote"))?,
  88. };
  89. tracing::debug!("Attempting mint for: {}", payment_method);
  90. let mut amount_minted = Amount::ZERO;
  91. let mut proof_streams = wallet.proof_stream(quote, SplitTarget::default(), None);
  92. while let Some(proofs) = proof_streams.next().await {
  93. let proofs = match proofs {
  94. Ok(proofs) => proofs,
  95. Err(err) => {
  96. tracing::error!("Proof streams ended with {:?}", err);
  97. break;
  98. }
  99. };
  100. amount_minted += proofs.total_amount()?;
  101. }
  102. println!("Received {amount_minted} from mint {mint_url}");
  103. Ok(())
  104. }