Skip to content

Commit

Permalink
chore: support mints with multiple keysets
Browse files Browse the repository at this point in the history
  • Loading branch information
ngutech21 committed Apr 10, 2024
1 parent 5e880e8 commit b835fee
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 39 deletions.
27 changes: 12 additions & 15 deletions moksha-cli/src/bin/moksha-cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use moksha_wallet::client::CashuClient;

use moksha_wallet::http::CrossPlatformHttpClient;

use moksha_wallet::localstore::WalletKeysetFilter;
use mokshacli::cli::{self, choose_mint, get_mints_with_balance};
use num_format::{Locale, ToFormattedString};
use qrcode::render::unicode;
Expand Down Expand Up @@ -151,9 +152,8 @@ async fn main() -> anyhow::Result<()> {

let wallet_keysets = wallet.get_wallet_keysets().await?;
let wallet_keyset = wallet_keysets
.iter()
.find(|k| k.mint_url == token_mint_url)
.expect("Keyset not found");
.get_active(&token_mint_url, &CurrencyUnit::Sat)
.expect("no active keyset found");

wallet.receive_tokens(wallet_keyset, &token).await?;
cli::show_total_balance(&wallet).await?;
Expand All @@ -170,9 +170,8 @@ async fn main() -> anyhow::Result<()> {

let wallet_keysets = wallet.get_wallet_keysets().await?;
let wallet_keyset = wallet_keysets
.iter()
.find(|k| k.mint_url == mint_url)
.expect("Keyset not found");
.get_active(&mint_url, &CurrencyUnit::Sat)
.expect("no active keyset found");

term.write_line(&format!("Using tokens from mint: {mint_url}"))?;
let result = wallet.send_tokens(wallet_keyset, amount).await?;
Expand Down Expand Up @@ -201,15 +200,15 @@ async fn main() -> anyhow::Result<()> {
cli::show_total_balance(&wallet).await?;
}
Command::Pay { invoice } => {
let mint_url = choose_mint(&wallet, &CurrencyUnit::Sat).await?.0;
let currency_unit = CurrencyUnit::Sat;
let mint_url = choose_mint(&wallet, &currency_unit).await?.0;
let wallet_keysets = wallet.get_wallet_keysets().await?;
let wallet_keyset = wallet_keysets
.iter()
.find(|k| k.mint_url == mint_url)
.expect("Keyset not found");
.get_active(&mint_url, &currency_unit)
.expect("no active keyset found");

let quote = wallet
.get_melt_quote_bolt11(&mint_url, invoice.clone(), CurrencyUnit::Sat)
.get_melt_quote_bolt11(&mint_url, invoice.clone(), currency_unit)
.await?;

let pay_confirmed = Confirm::new()
Expand Down Expand Up @@ -254,8 +253,7 @@ async fn main() -> anyhow::Result<()> {

let wallet_keysets = wallet.get_wallet_keysets().await?;
let wallet_keyset = wallet_keysets
.iter()
.find(|k| k.mint_url == mint_url)
.get_active(&mint_url, &CurrencyUnit::Sat)
.expect("Keyset not found");

let info = wallet.get_mint_info(&mint_url).await?;
Expand Down Expand Up @@ -398,8 +396,7 @@ async fn main() -> anyhow::Result<()> {

let wallet_keysets = wallet.get_wallet_keysets().await?;
let wallet_keyset = wallet_keysets
.iter()
.find(|k| k.mint_url == mint_url)
.get_active(&mint_url, &CurrencyUnit::Sat)
.expect("Keyset not found");

let progress_bar = cli::progress_bar()?;
Expand Down
2 changes: 1 addition & 1 deletion moksha-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub async fn get_mints_with_balance(
}
Ok(keysets
.into_iter()
.filter(|k| &k.currency_unit == currency_unit)
.filter(|k| &k.currency_unit == currency_unit && k.active)
.map(|k| {
(
k.mint_url,
Expand Down
32 changes: 19 additions & 13 deletions moksha-wallet/src/http/reqwest.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::CrossPlatformHttpClient;
use crate::error::MokshaWalletError;
use moksha_core::primitives::CashuErrorResponse;
use reqwest::{
header::{HeaderValue, CONTENT_TYPE},
Response, StatusCode,
};
use serde_json::Value;
use url::Url;

impl CrossPlatformHttpClient {
Expand All @@ -23,32 +23,38 @@ impl CrossPlatformHttpClient {
match serde_json::from_str::<T>(&response_text) {
Ok(data) => Ok(data),
Err(_) => {
let data = serde_json::from_str::<CashuErrorResponse>(&response_text)
// FIXME cleanup code
let data: Value = serde_json::from_str(&response_text)
.map_err(|_| MokshaWalletError::UnexpectedResponse(response_text))
.unwrap();
.expect("invalid value");
let detail = data["detail"].as_str().expect("detail not found");
// let data = serde_json::from_str::<CashuErrorResponse>(&response_text)
// .map_err(|_| MokshaWalletError::UnexpectedResponse(response_text))
// .unwrap();

// FIXME: use the error code to return a proper error
match data.detail.as_str() {
match detail {
"Lightning invoice not paid yet." => {
Err(MokshaWalletError::InvoiceNotPaidYet(data.code, data.detail))
Err(MokshaWalletError::InvoiceNotPaidYet(0, detail.to_owned()))
}
_ => Err(MokshaWalletError::MintError(data.detail)),
_ => Err(MokshaWalletError::MintError(detail.to_owned())),
}
}
}
}
_ => {
let txt = response.text().await?;
let data = serde_json::from_str::<CashuErrorResponse>(&txt)
.map_err(|_| MokshaWalletError::UnexpectedResponse(txt))
.unwrap();
let response_text = response.text().await?;
let data: Value = serde_json::from_str(&response_text)
.map_err(|_| MokshaWalletError::UnexpectedResponse(response_text))
.expect("invalid value");
let detail = data["detail"].as_str().expect("detail not found");

// FIXME: use the error code to return a proper error
match data.detail.as_str() {
match detail {
"Lightning invoice not paid yet." => {
Err(MokshaWalletError::InvoiceNotPaidYet(data.code, data.detail))
Err(MokshaWalletError::InvoiceNotPaidYet(0, detail.to_owned()))
}
_ => Err(MokshaWalletError::MintError(data.detail)),
_ => Err(MokshaWalletError::MintError(detail.to_owned())),
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions moksha-wallet/src/localstore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ pub struct WalletKeyset {
pub active: bool,
}

impl WalletKeysetFilter for Vec<WalletKeyset> {
fn get_active(&self, mint_url: &Url, currency_unit: &CurrencyUnit) -> Option<&WalletKeyset> {
self.iter()
.find(|k| k.mint_url == *mint_url && k.currency_unit == *currency_unit && k.active)
}
}

pub trait WalletKeysetFilter {
fn get_active(&self, mint_url: &Url, currency_unit: &CurrencyUnit) -> Option<&WalletKeyset>;
}

impl WalletKeyset {
pub fn new(
keyset_id: &KeysetId,
Expand Down
29 changes: 19 additions & 10 deletions moksha-wallet/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,27 +210,35 @@ where
return Err(MokshaWalletError::UnsupportedApiVersion);
}

// FIXME cleanup code
let mint_keysets = self.client.get_keysets(mint_url).await?;

let mut tx = self.localstore.begin_tx().await?;
let mut result = vec![];
for keyset in mint_keysets.keysets.iter() {
let public_keys = self
let keysets = self
.client
.get_keys_by_id(mint_url, keyset.id.clone())
.await?
.keysets
.into_iter()
.find(|k| k.id == keyset.id)
.expect("no valid keyset found")
.keys
.clone();
.await;

let public_keys = match keysets {
Ok(k) => k
.keysets
.into_iter()
.find(|k| k.id == keyset.id && k.unit == keyset.unit)
.expect("no valid keyset found")
.keys
.clone(),
Err(_) => {
//println!("Ignoring keyset without public_keys {:?}", keyset.id);
continue;
}
};

// ignore legacy keysets
let keyset_id = match KeysetId::new(&keyset.id) {
Ok(id) => id,
Err(_) => {
//println!("Ignoring legacy keyset {:?}", keyset.id);
continue;
}
};
Expand All @@ -243,6 +251,7 @@ where
public_keys,
keyset.active,
);

result.push(wallet_keyset.clone());
self.localstore
.upsert_keyset(&mut tx, &wallet_keyset)
Expand Down Expand Up @@ -496,7 +505,7 @@ where
let keyset = all_keysets
.iter()
.find(|k| k.keyset_id == *keyset_id)
.expect("keyset not found");
.expect("keyset not found create-secrets");

let start_index = (keyset.last_index + 1) as u32;
let secret_range = self.secret.derive_range(keyset_id, start_index, amount)?;
Expand Down

0 comments on commit b835fee

Please sign in to comment.