Skip to content

Commit

Permalink
feat: mint multiple
Browse files Browse the repository at this point in the history
feat: cln any amount multiple times

feat: cli remint

fix: insert supported units

fix: amount paid

fix: add bolt12

fix: fix mint state

feat: add logging

feat: hackathosne
  • Loading branch information
thesimplekid committed Oct 13, 2024
1 parent 06ea79a commit 962e614
Show file tree
Hide file tree
Showing 21 changed files with 227 additions and 22 deletions.
11 changes: 11 additions & 0 deletions crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ enum Commands {
MintInfo(sub_commands::mint_info::MintInfoSubcommand),
/// Mint proofs via bolt11
Mint(sub_commands::mint::MintSubCommand),
/// Remint
ReMint(sub_commands::remint_bolt12::ReMintSubCommand),
/// Burn Spent tokens
Burn(sub_commands::burn::BurnSubCommand),
/// Restore proofs from seed
Expand Down Expand Up @@ -199,5 +201,14 @@ async fn main() -> Result<()> {
sub_commands::update_mint_url::update_mint_url(&multi_mint_wallet, sub_command_args)
.await
}
Commands::ReMint(sub_command_args) => {
sub_commands::remint_bolt12::remint(
&multi_mint_wallet,
&mnemonic.to_seed_normalized(""),
localstore,
sub_command_args,
)
.await
}
}
}
1 change: 1 addition & 0 deletions crates/cdk-cli/src/sub_commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod mint;
pub mod mint_info;
pub mod pending_mints;
pub mod receive;
pub mod remint_bolt12;
pub mod restore;
pub mod send;
pub mod update_mint_url;
54 changes: 54 additions & 0 deletions crates/cdk-cli/src/sub_commands/remint_bolt12.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::sync::Arc;

use anyhow::Result;
use cdk::amount::SplitTarget;
use cdk::cdk_database::{Error, WalletDatabase};
use cdk::mint_url::MintUrl;
use cdk::nuts::CurrencyUnit;
use cdk::wallet::multi_mint_wallet::WalletKey;
use cdk::wallet::{MultiMintWallet, Wallet};
use clap::Args;
use serde::{Deserialize, Serialize};

#[derive(Args, Serialize, Deserialize)]
pub struct ReMintSubCommand {
/// Mint url
mint_url: MintUrl,
#[arg(long)]
quote_id: String,
}

pub async fn remint(
multi_mint_wallet: &MultiMintWallet,
seed: &[u8],
localstore: Arc<dyn WalletDatabase<Err = Error> + Sync + Send>,
sub_command_args: &ReMintSubCommand,
) -> Result<()> {
let mint_url = sub_command_args.mint_url.clone();
let quote_id = sub_command_args.quote_id.clone();

let wallet = match multi_mint_wallet
.get_wallet(&WalletKey::new(mint_url.clone(), CurrencyUnit::Sat))
.await
{
Some(wallet) => wallet.clone(),
None => {
let wallet = Wallet::new(
&mint_url.to_string(),
CurrencyUnit::Sat,
localstore,
seed,
None,
)?;

multi_mint_wallet.add_wallet(wallet.clone()).await;
wallet
}
};

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

println!("Received {receive_amount} from mint {mint_url}");

Ok(())
}
15 changes: 10 additions & 5 deletions crates/cdk-cln/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl MintLightning for Cln {
// Clippy thinks select is not stable but it compiles fine on MSRV (1.63.0)
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
let last_pay_index = self.get_last_pay_index().await?;
let cln_client = cln_rpc::ClnRpc::new(&self.rpc_socket).await?;

Expand Down Expand Up @@ -162,6 +162,11 @@ impl MintLightning for Cln {

let payment_hash = wait_any_response.payment_hash.to_string();


// TODO: Handle unit conversion
let amount_msats = wait_any_response.amount_received_msat.expect("status is paid there should be an amount");
let amount_sats = amount_msats.msat() / 1000;

let request_look_up = match wait_any_response.bolt12 {
// If it is a bolt12 payment we need to get the offer_id as this is what we use as the request look up.
// Since this is not returned in the wait any response,
Expand Down Expand Up @@ -192,7 +197,7 @@ impl MintLightning for Cln {
None => payment_hash,
};

break Some((request_look_up, (cln_client, last_pay_idx, cancel_token, is_active)));
break Some(((request_look_up, amount_sats.into()), (cln_client, last_pay_idx, cancel_token, is_active)));
}
Err(e) => {
tracing::warn!("Error fetching invoice: {e}");
Expand Down Expand Up @@ -597,7 +602,7 @@ impl MintLightning for Cln {

let label = Uuid::new_v4().to_string();

let amount = to_unit(amount, unit, &CurrencyUnit::Msat)?;
let _amount = to_unit(amount, unit, &CurrencyUnit::Msat)?;

let cln_response = cln_client
.call(cln_rpc::Request::Offer(OfferRequest {
Expand All @@ -611,8 +616,8 @@ impl MintLightning for Cln {
recurrence_limit: None,
recurrence_paywindow: None,
recurrence_start_any_period: None,
single_use: Some(true),
amount: amount.to_string(),
single_use: Some(false),
amount: "any".to_string(),
}))
.await
.map_err(Error::from)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-fake-wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ impl MintLightning for FakeWallet {

async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
let receiver = self.receiver.lock().await.take().ok_or(Error::NoReceiver)?;
let receiver_stream = ReceiverStream::new(receiver);
self.wait_invoice_is_active.store(true, Ordering::SeqCst);
Ok(Box::pin(receiver_stream.map(|label| label)))
Ok(Box::pin(receiver_stream.map(|label| (label, Amount::ZERO))))
}

async fn get_payment_quote(
Expand Down
5 changes: 4 additions & 1 deletion crates/cdk-integration-tests/tests/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,14 @@ async fn mint_proofs(
amount,
unix_time() + 36000,
request_lookup.to_string(),
Amount::ZERO,
Amount::ZERO,
);

mint.localstore.add_mint_quote(quote.clone()).await?;

mint.pay_mint_quote_for_request_id(&request_lookup).await?;
mint.pay_mint_quote_for_request_id(&request_lookup, amount)
.await?;
let keyset_id = Id::from(&keys);

let premint = PreMintSecrets::random(keyset_id, amount, split_target)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-lnbits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl MintLightning for LNbits {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
let receiver = self
.receiver
.lock()
Expand Down Expand Up @@ -129,7 +129,7 @@ impl MintLightning for LNbits {
match check {
Ok(state) => {
if state {
Some((msg, (receiver, lnbits_api, cancel_token, is_active)))
Some(((msg, Amount::ZERO), (receiver, lnbits_api, cancel_token, is_active)))
} else {
None
}
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-lnd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl MintLightning for Lnd {

async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
let mut client =
fedimint_tonic_lnd::connect(self.address.clone(), &self.cert_file, &self.macaroon_file)
.await
Expand Down Expand Up @@ -141,7 +141,7 @@ impl MintLightning for Lnd {
match msg {
Ok(Some(msg)) => {
if msg.state == 1 {
Some((hex::encode(msg.r_hash), (stream, cancel_token, is_active)))
Some(((hex::encode(msg.r_hash), Amount::ZERO), (stream, cancel_token, is_active)))
} else {
None
}
Expand Down
13 changes: 13 additions & 0 deletions crates/cdk-mintd/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ async fn main() -> anyhow::Result<()> {
CurrencyUnit::Sat,
PaymentMethod::Bolt11,
mint_melt_limits,
cln.clone(),
);

let ln_key = LnKey {
unit: CurrencyUnit::Sat,
method: PaymentMethod::Bolt12,
};
ln_backends.insert(ln_key, cln.clone());

mint_builder = mint_builder.add_ln_backend(
CurrencyUnit::Sat,
PaymentMethod::Bolt12,
mint_melt_limits,
cln,
)
}
Expand Down
5 changes: 5 additions & 0 deletions crates/cdk-mintd/src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ impl MintBuilder {

ln.insert(ln_key, ln_backend);

let mut supported_units = self.supported_units.clone();

supported_units.insert(ln_key.unit, (0, 32));
self.supported_units = supported_units;

self.ln = Some(ln);

self
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-phoenixd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl MintLightning for Phoenixd {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
let receiver = self
.receiver
.lock()
Expand Down Expand Up @@ -136,7 +136,7 @@ impl MintLightning for Phoenixd {
Ok(state) => {
if state.is_paid {
// Yield the payment hash and continue the stream
Some((msg.payment_hash, (receiver, phoenixd_api, cancel_token, is_active)))
Some(((msg.payment_hash, Amount::ZERO), (receiver, phoenixd_api, cancel_token, is_active)))
} else {
// Invoice not paid yet, continue waiting
// We need to continue the stream, so we return the same state
Expand Down
3 changes: 3 additions & 0 deletions crates/cdk-redb/src/mint/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ impl From<V1MintQuote> for MintQuote {
state: quote.state,
expiry: quote.expiry,
request_lookup_id: Bolt11Invoice::from_str(&quote.request).unwrap().to_string(),
// TODO: Create real migrations
amount_paid: Amount::ZERO,
amount_issued: Amount::ZERO,
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/cdk-sqlite/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,9 @@ fn sqlite_row_to_mint_quote(row: SqliteRow) -> Result<MintQuote, Error> {
state: MintQuoteState::from_str(&row_state).map_err(Error::from)?,
expiry: row_expiry as u64,
request_lookup_id,
// TODO: Get these values
amount_paid: Amount::ZERO,
amount_issued: Amount::ZERO,
})
}

Expand Down
4 changes: 2 additions & 2 deletions crates/cdk-strike/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl MintLightning for Strike {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
self.strike_api
.subscribe_to_invoice_webhook(self.webhook_url.clone())
.await?;
Expand Down Expand Up @@ -129,7 +129,7 @@ impl MintLightning for Strike {
match check {
Ok(state) => {
if state.state == InvoiceState::Paid {
Some((msg, (receiver, strike_api, cancel_token, is_active)))
Some(((msg, Amount::ZERO), (receiver, strike_api, cancel_token, is_active)))
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion crates/cdk/src/cdk_lightning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub trait MintLightning {
/// Returns a stream of request_lookup_id once invoices are paid
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = String> + Send>>, Self::Err>;
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err>;

/// Is wait invoice active
fn is_wait_invoice_active(&self) -> bool;
Expand Down
2 changes: 2 additions & 0 deletions crates/cdk/src/mint/mint_18.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ impl Mint {
amount,
create_invoice_response.expiry.unwrap_or(0),
create_invoice_response.request_lookup_id.clone(),
Amount::ZERO,
Amount::ZERO,
);

tracing::debug!(
Expand Down
Loading

0 comments on commit 962e614

Please sign in to comment.