auth_wallet.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #![allow(missing_docs)]
  2. use std::sync::Arc;
  3. use std::time::Duration;
  4. use cdk::error::Error;
  5. use cdk::nuts::{CurrencyUnit, PaymentMethod};
  6. use cdk::wallet::{SendOptions, Wallet};
  7. use cdk::{Amount, OidcClient};
  8. use cdk_common::amount::SplitTarget;
  9. use cdk_common::{MintInfo, ProofsMethods};
  10. use cdk_sqlite::wallet::memory;
  11. use rand::Rng;
  12. use tracing_subscriber::EnvFilter;
  13. const TEST_USERNAME: &str = "cdk-test";
  14. const TEST_PASSWORD: &str = "cdkpassword";
  15. #[tokio::main]
  16. async fn main() -> Result<(), Error> {
  17. // Set up logging
  18. let default_filter = "debug";
  19. let sqlx_filter = "sqlx=warn,hyper_util=warn,reqwest=warn,rustls=warn";
  20. let env_filter = EnvFilter::new(format!("{},{}", default_filter, sqlx_filter));
  21. tracing_subscriber::fmt().with_env_filter(env_filter).init();
  22. // Initialize the memory store for the wallet
  23. let localstore = memory::empty().await?;
  24. // Generate a random seed for the wallet
  25. let seed = rand::rng().random::<[u8; 64]>();
  26. // Define the mint URL and currency unit
  27. let mint_url = "http://127.0.0.1:8085";
  28. let unit = CurrencyUnit::Sat;
  29. let amount = Amount::from(50);
  30. // Create a new wallet
  31. let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), seed, None)?;
  32. let mint_info = wallet
  33. .fetch_mint_info()
  34. .await
  35. .expect("mint info")
  36. .expect("could not get mint info");
  37. // Request a mint quote from the wallet
  38. let quote = wallet
  39. .mint_quote(PaymentMethod::BOLT11, Some(amount), None, None)
  40. .await;
  41. println!("Minting nuts ... {:?}", quote);
  42. // Getting the CAT token is not inscope of cdk and expected to be handled by the implemntor
  43. // We just use this helper fn with password auth for testing
  44. let access_token = get_access_token(&mint_info).await;
  45. wallet.set_cat(access_token).await.unwrap();
  46. wallet
  47. .mint_blind_auth(10.into())
  48. .await
  49. .expect("Could not mint blind auth");
  50. let quote = wallet
  51. .mint_quote(PaymentMethod::BOLT11, Some(amount), None, None)
  52. .await
  53. .unwrap();
  54. let proofs = wallet
  55. .wait_and_mint_quote(quote, SplitTarget::default(), None, Duration::from_secs(10))
  56. .await
  57. .unwrap();
  58. println!("Received: {}", proofs.total_amount()?);
  59. // Get the total balance of the wallet
  60. let balance = wallet.total_balance().await?;
  61. println!("Wallet balance: {}", balance);
  62. let prepared_send = wallet
  63. .prepare_send(10.into(), SendOptions::default())
  64. .await?;
  65. let token = prepared_send.confirm(None).await?;
  66. println!("Created token: {}", token);
  67. let remaining_blind_auth = wallet.get_unspent_auth_proofs().await?.len();
  68. // We started with 10 blind tokens we expect 8 ath this point
  69. // 1 is used for the mint quote + 1 used for the mint
  70. // The swap is not expected to use one as it will be offline or we have "/swap" as an unprotected endpoint in the mint config
  71. assert_eq!(remaining_blind_auth, 8);
  72. println!("Remaining blind auth: {}", remaining_blind_auth);
  73. Ok(())
  74. }
  75. async fn get_access_token(mint_info: &MintInfo) -> String {
  76. let openid_discovery = mint_info
  77. .nuts
  78. .nut21
  79. .clone()
  80. .expect("Nut21 defined")
  81. .openid_discovery;
  82. let oidc_client = OidcClient::new(openid_discovery, None);
  83. // Get the token endpoint from the OIDC configuration
  84. let token_url = oidc_client
  85. .get_oidc_config()
  86. .await
  87. .expect("Failed to get OIDC config")
  88. .token_endpoint;
  89. let client_id = oidc_client
  90. .get_oidc_config()
  91. .await
  92. .expect("Failed to get OIDC config")
  93. .token_endpoint;
  94. // Create the request parameters
  95. let params = [
  96. ("grant_type", "password"),
  97. ("client_id", &client_id),
  98. ("username", TEST_USERNAME),
  99. ("password", TEST_PASSWORD),
  100. ];
  101. // Make the token request directly
  102. let client = reqwest::Client::new();
  103. let response = client
  104. .post(token_url)
  105. .form(&params)
  106. .send()
  107. .await
  108. .expect("Failed to send token request");
  109. let token_response: serde_json::Value = response
  110. .json()
  111. .await
  112. .expect("Failed to parse token response");
  113. token_response["access_token"]
  114. .as_str()
  115. .expect("No access token in response")
  116. .to_string()
  117. }