use std::sync::Arc;
use cdk::amount::SplitTarget;
use cdk::error::Error;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload};
use cdk::wallet::{SendOptions, Wallet, WalletSubscription};
use cdk::{Amount, OidcClient};
use cdk_common::{MintInfo, ProofsMethods};
use cdk_sqlite::wallet::memory;
use rand::Rng;
use tracing_subscriber::EnvFilter;
const TEST_USERNAME: &str = "cdk-test";
const TEST_PASSWORD: &str = "cdkpassword";
#[tokio::main]
async fn main() -> Result<(), Error> {
let default_filter = "debug";
let sqlx_filter = "sqlx=warn,hyper_util=warn,reqwest=warn,rustls=warn";
let env_filter = EnvFilter::new(format!("{},{}", default_filter, sqlx_filter));
tracing_subscriber::fmt().with_env_filter(env_filter).init();
let localstore = memory::empty().await?;
let seed = rand::thread_rng().gen::<[u8; 32]>();
let mint_url = "http://127.0.0.1:8085";
let unit = CurrencyUnit::Sat;
let amount = Amount::from(50);
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?;
let mint_info = wallet
.get_mint_info()
.await
.expect("mint info")
.expect("could not get mint info");
let quote = wallet.mint_quote(amount, None).await;
println!("Minting nuts ... {:?}", quote);
let access_token = get_access_token(&mint_info).await;
wallet.set_cat(access_token).await.unwrap();
wallet
.mint_blind_auth(10.into())
.await
.expect("Could not mint blind auth");
let quote = wallet.mint_quote(amount, None).await?;
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
let receive_amount = wallet.mint("e.id, SplitTarget::default(), None).await?;
println!("Received: {}", receive_amount.total_amount()?);
let balance = wallet.total_balance().await?;
println!("Wallet balance: {}", balance);
let prepared_send = wallet
.prepare_send(10.into(), SendOptions::default())
.await?;
let token = wallet.send(prepared_send, None).await?;
println!("Created token: {}", token);
let remaining_blind_auth = wallet.get_unspent_auth_proofs().await?.len();
assert_eq!(remaining_blind_auth, 8);
println!("Remaining blind auth: {}", remaining_blind_auth);
Ok(())
}
async fn get_access_token(mint_info: &MintInfo) -> String {
let openid_discovery = mint_info
.nuts
.nut21
.clone()
.expect("Nut21 defined")
.openid_discovery;
let oidc_client = OidcClient::new(openid_discovery);
let token_url = oidc_client
.get_oidc_config()
.await
.expect("Failed to get OIDC config")
.token_endpoint;
let params = [
("grant_type", "password"),
("client_id", "cashu-client"),
("username", TEST_USERNAME),
("password", TEST_PASSWORD),
];
let client = reqwest::Client::new();
let response = client
.post(token_url)
.form(¶ms)
.send()
.await
.expect("Failed to send token request");
let token_response: serde_json::Value = response
.json()
.await
.expect("Failed to parse token response");
token_response["access_token"]
.as_str()
.expect("No access token in response")
.to_string()
}