Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Wallet TransactionDatabase; Create WalletBuilder #581

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions crates/cashu/src/nuts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub use nut04::{
MintQuoteBolt11Response, QuoteState as MintQuoteState, Settings as NUT04Settings,
};
pub use nut05::{
MeltBolt11Request, MeltMethodSettings, MeltOptions, MeltQuoteBolt11Request,
MeltQuoteBolt11Response, QuoteState as MeltQuoteState, Settings as NUT05Settings,
MeltBolt11Request, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteBolt11Response,
MeltQuoteOptions, QuoteState as MeltQuoteState, Settings as NUT05Settings,
};
pub use nut06::{ContactInfo, MintInfo, MintVersion, Nuts};
pub use nut07::{CheckStateRequest, CheckStateResponse, ProofState, State};
Expand Down
8 changes: 4 additions & 4 deletions crates/cashu/src/nuts/nut05.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,22 @@ pub struct MeltQuoteBolt11Request {
/// Unit wallet would like to pay with
pub unit: CurrencyUnit,
/// Payment Options
pub options: Option<MeltOptions>,
pub options: Option<MeltQuoteOptions>,
}

/// Melt Options
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))]
pub enum MeltOptions {
pub enum MeltQuoteOptions {
/// Mpp Options
Mpp {
/// MPP
mpp: Mpp,
},
}

impl MeltOptions {
impl MeltQuoteOptions {
/// Create new [`Options::Mpp`]
pub fn new_mpp<A>(amount: A) -> Self
where
Expand Down Expand Up @@ -100,7 +100,7 @@ impl MeltQuoteBolt11Request {
.amount_milli_satoshis()
.ok_or(Error::InvalidAmountRequest)?
.into()),
Some(MeltOptions::Mpp { mpp }) => Ok(mpp.amount),
Some(MeltQuoteOptions::Mpp { mpp }) => Ok(mpp.amount),
}
}
}
Expand Down
90 changes: 35 additions & 55 deletions crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::sync::Arc;
use anyhow::{bail, Result};
use bip39::rand::{thread_rng, Rng};
use bip39::Mnemonic;
use cdk::cdk_database;
use cdk::cdk_database::WalletDatabase;
use cdk::cdk_database::WalletProofDatabase;
use cdk::nuts::CurrencyUnit;
use cdk::wallet::client::HttpClient;
use cdk::wallet::{MultiMintWallet, Wallet};
use cdk::wallet::{MultiMintWallet, Wallet, WalletBuilder};
use cdk_redb::WalletRedbDatabase;
use cdk_sqlite::WalletSqliteDatabase;
use clap::{Parser, Subcommand};
Expand Down Expand Up @@ -102,24 +102,6 @@ async fn main() -> Result<()> {

fs::create_dir_all(&work_dir)?;

let localstore: Arc<dyn WalletDatabase<Err = cdk_database::Error> + Send + Sync> =
match args.engine.as_str() {
"sqlite" => {
let sql_path = work_dir.join("cdk-cli.sqlite");
let sql = WalletSqliteDatabase::new(&sql_path).await?;

sql.migrate().await;

Arc::new(sql)
}
"redb" => {
let redb_path = work_dir.join("cdk-cli.redb");

Arc::new(WalletRedbDatabase::new(&redb_path)?)
}
_ => bail!("Unknown DB engine"),
};

let seed_path = work_dir.join("seed");

let mnemonic = match fs::metadata(seed_path.clone()) {
Expand All @@ -140,24 +122,40 @@ async fn main() -> Result<()> {
}
};

let mut wallets: Vec<Wallet> = Vec::new();
let mut builder = WalletBuilder::new(mnemonic.to_seed_normalized("").to_vec());

let mints = match args.engine.as_str() {
"sqlite" => {
let sql_path = work_dir.join("cdk-cli.sqlite");
let sql = WalletSqliteDatabase::new(&sql_path).await?;

let mints = localstore.get_mints().await?;
sql.migrate().await;

let db = Arc::new(sql);
builder = builder.proof_db(db.clone()).transaction_db(db.clone());
db.get_mints().await?
}
"redb" => {
let redb_path = work_dir.join("cdk-cli.redb");

let db = Arc::new(WalletRedbDatabase::new(&redb_path)?);
builder = builder.proof_db(db.clone()).transaction_db(db.clone());
db.get_mints().await?
}
_ => bail!("Unknown DB engine"),
};

let mut wallets: Vec<Wallet> = Vec::new();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make something more reusable? A single place to convert a string into the struct, something like this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems like a good idea for another PR.


for (mint_url, _) in mints {
let mut wallet = Wallet::new(
&mint_url.to_string(),
cdk::nuts::CurrencyUnit::Sat,
localstore.clone(),
&mnemonic.to_seed_normalized(""),
None,
)?;
let mut builder = builder.clone();

if let Some(proxy_url) = args.proxy.as_ref() {
let http_client = HttpClient::with_proxy(mint_url, proxy_url.clone(), None, true)?;
wallet.set_client(http_client);
let http_client =
HttpClient::with_proxy(mint_url.clone(), proxy_url.clone(), None, true)?;
builder = builder.client(Arc::new(http_client));
}

wallets.push(wallet);
wallets.push(builder.build(mint_url, CurrencyUnit::Sat)?);
}

let multi_mint_wallet = MultiMintWallet::new(wallets);
Expand All @@ -171,13 +169,7 @@ async fn main() -> Result<()> {
sub_commands::melt::pay(&multi_mint_wallet, sub_command_args).await
}
Commands::Receive(sub_command_args) => {
sub_commands::receive::receive(
&multi_mint_wallet,
localstore,
&mnemonic.to_seed_normalized(""),
sub_command_args,
)
.await
sub_commands::receive::receive(&multi_mint_wallet, builder, sub_command_args).await
}
Commands::Send(sub_command_args) => {
sub_commands::send::send(&multi_mint_wallet, sub_command_args).await
Expand All @@ -189,13 +181,7 @@ async fn main() -> Result<()> {
sub_commands::mint_info::mint_info(args.proxy, sub_command_args).await
}
Commands::Mint(sub_command_args) => {
sub_commands::mint::mint(
&multi_mint_wallet,
&mnemonic.to_seed_normalized(""),
localstore,
sub_command_args,
)
.await
sub_commands::mint::mint(&multi_mint_wallet, builder, sub_command_args).await
}
Commands::MintPending => {
sub_commands::pending_mints::mint_pending(&multi_mint_wallet).await
Expand All @@ -204,13 +190,7 @@ async fn main() -> Result<()> {
sub_commands::burn::burn(&multi_mint_wallet, sub_command_args).await
}
Commands::Restore(sub_command_args) => {
sub_commands::restore::restore(
&multi_mint_wallet,
&mnemonic.to_seed_normalized(""),
localstore,
sub_command_args,
)
.await
sub_commands::restore::restore(&multi_mint_wallet, builder, sub_command_args).await
}
Commands::UpdateMintUrl(sub_command_args) => {
sub_commands::update_mint_url::update_mint_url(&multi_mint_wallet, sub_command_args)
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-cli/src/sub_commands/create_request.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use cdk::nuts::nut18::TransportType;
use cdk::nuts::{CurrencyUnit, PaymentRequest, PaymentRequestPayload, Token, Transport};
use cdk::wallet::MultiMintWallet;
use cdk::wallet::{MultiMintWallet, ReceiveOptions};
use clap::Args;
use nostr_sdk::nips::nip19::Nip19Profile;
use nostr_sdk::prelude::*;
Expand Down Expand Up @@ -83,7 +83,7 @@ pub async fn create_request(
let token = Token::new(payload.mint, payload.proofs, payload.memo, payload.unit);

let amount = multi_mint_wallet
.receive(&token.to_string(), &[], &[])
.receive(&token.to_string(), ReceiveOptions::default())
.await?;

println!("Received {}", amount);
Expand Down
9 changes: 5 additions & 4 deletions crates/cdk-cli/src/sub_commands/melt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use std::str::FromStr;

use anyhow::{bail, Result};
use cdk::amount::MSAT_IN_SAT;
use cdk::nuts::{CurrencyUnit, MeltOptions};
use cdk::nuts::{CurrencyUnit, MeltQuoteOptions};
use cdk::wallet::multi_mint_wallet::MultiMintWallet;
use cdk::wallet::types::WalletKey;
use cdk::wallet::MeltOptions;
use cdk::Bolt11Invoice;
use clap::Args;

Expand Down Expand Up @@ -57,7 +58,7 @@ pub async fn pay(
stdin.read_line(&mut user_input)?;
let bolt11 = Bolt11Invoice::from_str(user_input.trim())?;

let mut options: Option<MeltOptions> = None;
let mut options: Option<MeltQuoteOptions> = None;

if sub_command_args.mpp {
println!("Enter the amount you would like to pay in sats, for a mpp payment.");
Expand All @@ -74,7 +75,7 @@ pub async fn pay(
bail!("Not enough funds");
}

options = Some(MeltOptions::new_mpp(user_amount * MSAT_IN_SAT));
options = Some(MeltQuoteOptions::new_mpp(user_amount * MSAT_IN_SAT));
} else if bolt11
.amount_milli_satoshis()
.unwrap()
Expand All @@ -87,7 +88,7 @@ pub async fn pay(

println!("{:?}", quote);

let melt = wallet.melt(&quote.id).await?;
let melt = wallet.melt(&quote.id, MeltOptions::default()).await?;

println!("Paid invoice: {}", melt.state);
if let Some(preimage) = melt.preimage {
Expand Down
12 changes: 4 additions & 8 deletions crates/cdk-cli/src/sub_commands/mint.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use std::str::FromStr;
use std::sync::Arc;

use anyhow::{anyhow, Result};
use cdk::amount::SplitTarget;
use cdk::cdk_database::{Error, WalletDatabase};
use cdk::mint_url::MintUrl;
use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload};
use cdk::wallet::types::WalletKey;
use cdk::wallet::{MultiMintWallet, Wallet, WalletSubscription};
use cdk::wallet::{MintOptions, MultiMintWallet, WalletBuilder, WalletSubscription};
use cdk::Amount;
use clap::Args;
use serde::{Deserialize, Serialize};
Expand All @@ -32,8 +29,7 @@ pub struct MintSubCommand {

pub async fn mint(
multi_mint_wallet: &MultiMintWallet,
seed: &[u8],
localstore: Arc<dyn WalletDatabase<Err = Error> + Sync + Send>,
builder: WalletBuilder,
sub_command_args: &MintSubCommand,
) -> Result<()> {
let mint_url = sub_command_args.mint_url.clone();
Expand All @@ -46,7 +42,7 @@ pub async fn mint(
{
Some(wallet) => wallet.clone(),
None => {
let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?;
let wallet = builder.build(mint_url.clone(), CurrencyUnit::Sat)?;

multi_mint_wallet.add_wallet(wallet.clone()).await;
wallet
Expand Down Expand Up @@ -82,7 +78,7 @@ pub async fn mint(
Some(quote_id) => quote_id.to_string(),
};

let proofs = wallet.mint(&quote_id, SplitTarget::default(), None).await?;
let proofs = wallet.mint(&quote_id, MintOptions::default()).await?;

let receive_amount = proofs.total_amount()?;

Expand Down
12 changes: 5 additions & 7 deletions crates/cdk-cli/src/sub_commands/pay_request.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use std::io::{self, Write};

use anyhow::{anyhow, Result};
use cdk::amount::SplitTarget;
use cdk::nuts::nut18::TransportType;
use cdk::nuts::{PaymentRequest, PaymentRequestPayload};
use cdk::wallet::{MultiMintWallet, SendKind};
use cdk::wallet::{MultiMintWallet, SendOptions};
use clap::Args;
use nostr_sdk::nips::nip19::Nip19Profile;
use nostr_sdk::{Client as NostrClient, EventBuilder, FromBech32, Keys};
Expand Down Expand Up @@ -84,11 +83,10 @@ pub async fn pay_request(
let proofs = matching_wallet
.send(
amount,
None,
None,
&SplitTarget::default(),
&SendKind::default(),
true,
SendOptions {
include_fees: true,
..Default::default()
},
)
.await?
.proofs();
Expand Down
Loading
Loading