Skip to content

Commit 794187d

Browse files
committed
feat: cdk-cli cat login
1 parent 774cbbf commit 794187d

File tree

8 files changed

+125
-6
lines changed

8 files changed

+125
-6
lines changed

crates/cashu/src/nuts/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ pub use nut14::HTLCWitness;
5757
pub use nut15::{Mpp, MppMethodSettings, Settings as NUT15Settings};
5858
pub use nut17::NotificationPayload;
5959
pub use nut18::{PaymentRequest, PaymentRequestPayload, Transport};
60-
pub use nutxx::{Method, ProtectedEndpoint, RoutePath};
60+
pub use nutxx::{Method, OidcClient, ProtectedEndpoint, RoutePath};
6161
pub use nutxx1::{AuthProof, AuthRequired, AuthToken, BlindAuthToken};

crates/cashu/src/nuts/nutxx/oidc.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use std::collections::HashMap;
55
use jsonwebtoken::jwk::{AlgorithmParameters, JwkSet};
66
use jsonwebtoken::{decode, decode_header, DecodingKey, Validation};
77
use reqwest::Client;
8-
use serde::Deserialize;
8+
use serde::{Deserialize, Serialize};
9+
use serde_json::Value;
910
use thiserror::Error;
1011
use tracing::instrument;
1112

@@ -34,6 +35,7 @@ pub enum Error {
3435
pub struct OidcConfig {
3536
pub jwks_uri: String,
3637
pub issuer: String,
38+
pub token_endpoint: String,
3739
}
3840

3941
/// Http Client
@@ -43,6 +45,14 @@ pub struct OidcClient {
4345
openid_discovery: String,
4446
}
4547

48+
#[derive(Debug, Clone, Serialize)]
49+
pub struct AccessTokenRequest {
50+
pub grant_type: String,
51+
pub client_id: String,
52+
pub username: String,
53+
pub password: String,
54+
}
55+
4656
impl OidcClient {
4757
/// Create new [`OidcClient`]
4858
pub fn new(openid_discovery: String) -> Self {
@@ -116,4 +126,34 @@ impl OidcClient {
116126

117127
Ok(())
118128
}
129+
130+
pub async fn get_access_token(
131+
&self,
132+
username: String,
133+
password: String,
134+
) -> Result<String, Error> {
135+
let token_url = self.get_oidc_config().await?.token_endpoint;
136+
137+
let request = AccessTokenRequest {
138+
grant_type: "password".to_string(),
139+
client_id: "cashu-client".to_string(),
140+
username,
141+
password,
142+
};
143+
144+
let response: Value = self
145+
.inner
146+
.post(token_url)
147+
.form(&request)
148+
.send()
149+
.await?
150+
.json()
151+
.await?;
152+
153+
println!("{:?}", response);
154+
155+
let token = response.get("access_token").expect("access token");
156+
157+
Ok(token.to_string())
158+
}
119159
}

crates/cdk-cli/src/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ enum Commands {
7979
CreateRequest(sub_commands::create_request::CreateRequestSubCommand),
8080
/// Mint blind auth proofs
8181
MintBlindAuth(sub_commands::mint_blind_auth::MintBlindAuthSubCommand),
82+
/// Cat login
83+
CatLogin(sub_commands::cat_login::CatLoginSubCommand),
8284
}
8385

8486
#[tokio::main]
@@ -239,5 +241,14 @@ async fn main() -> Result<()> {
239241
)
240242
.await
241243
}
244+
Commands::CatLogin(sub_command_args) => {
245+
sub_commands::cat_login::cat_login(
246+
&multi_mint_wallet,
247+
&mnemonic.to_seed_normalized(""),
248+
localstore,
249+
sub_command_args,
250+
)
251+
.await
252+
}
242253
}
243254
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use std::str::FromStr;
2+
use std::sync::Arc;
3+
4+
use anyhow::Result;
5+
use cdk::cdk_database::{Error, WalletDatabase};
6+
use cdk::mint_url::MintUrl;
7+
use cdk::nuts::nutxx::OidcClient;
8+
use cdk::nuts::CurrencyUnit;
9+
use cdk::wallet::types::WalletKey;
10+
use cdk::wallet::{MultiMintWallet, Wallet};
11+
use clap::Args;
12+
use serde::{Deserialize, Serialize};
13+
14+
#[derive(Args, Serialize, Deserialize)]
15+
pub struct CatLoginSubCommand {
16+
/// Mint url
17+
mint_url: MintUrl,
18+
/// Username
19+
username: String,
20+
/// Password
21+
password: String,
22+
/// Currency unit e.g. sat
23+
#[arg(default_value = "sat")]
24+
#[arg(short, long)]
25+
unit: String,
26+
}
27+
28+
pub async fn cat_login(
29+
multi_mint_wallet: &MultiMintWallet,
30+
seed: &[u8],
31+
localstore: Arc<dyn WalletDatabase<Err = Error> + Sync + Send>,
32+
sub_command_args: &CatLoginSubCommand,
33+
) -> Result<()> {
34+
let mint_url = sub_command_args.mint_url.clone();
35+
let unit = CurrencyUnit::from_str(&sub_command_args.unit)?;
36+
37+
let wallet = match multi_mint_wallet
38+
.get_wallet(&WalletKey::new(mint_url.clone(), unit.clone()))
39+
.await
40+
{
41+
Some(wallet) => wallet.clone(),
42+
None => {
43+
let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None, None)?;
44+
45+
multi_mint_wallet.add_wallet(wallet.clone()).await;
46+
wallet
47+
}
48+
};
49+
50+
let mint_info = wallet.get_mint_info().await?.expect("Mint info not found");
51+
52+
let openid_discovery = mint_info
53+
.nuts
54+
.nutxx
55+
.expect("Nutxx definded")
56+
.openid_discovery;
57+
58+
let oidc_client = OidcClient::new(openid_discovery);
59+
60+
let access_token = oidc_client
61+
.get_access_token(
62+
sub_command_args.username.clone(),
63+
sub_command_args.password.clone(),
64+
)
65+
.await?;
66+
67+
println!("access_token: {}", access_token);
68+
69+
Ok(())
70+
}

crates/cdk-cli/src/sub_commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod balance;
22
pub mod burn;
3+
pub mod cat_login;
34
pub mod check_spent;
45
pub mod create_request;
56
pub mod decode_request;

crates/cdk-sqlite/src/mint/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ fn sqlite_row_to_keyset_info(row: SqliteRow) -> Result<MintKeySetInfo, Error> {
12341234
let row_valid_to: Option<i64> = row.try_get("valid_to").map_err(Error::from)?;
12351235
let row_derivation_path: String = row.try_get("derivation_path").map_err(Error::from)?;
12361236
let row_max_order: u8 = row.try_get("max_order").map_err(Error::from)?;
1237-
let row_keyset_ppk: Option<i64> = row.try_get("input_fee_ppk").map_err(Error::from)?;
1237+
let row_keyset_ppk: Option<i64> = row.try_get("input_fee_ppk").ok();
12381238
let row_derivation_path_index: Option<i64> =
12391239
row.try_get("derivation_path_index").map_err(Error::from)?;
12401240

crates/cdk/src/mint/auth/auth_database.rs

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/cdk/src/mint/auth/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use super::{
88
use crate::dhke::{sign_message, verify_message};
99
use crate::Amount;
1010

11-
pub mod auth_database;
12-
1311
impl Mint {
1412
/// Check if and what kind of auth is required for a method
1513
pub fn protected(&self, method: &ProtectedEndpoint) -> Option<AuthRequired> {

0 commit comments

Comments
 (0)