From 0eef0ce142ddf7c94209907c436aaf0f1c5c3c11 Mon Sep 17 00:00:00 2001 From: Tony Giorgio Date: Wed, 31 Jan 2024 08:13:28 -0600 Subject: [PATCH] Estimates fedimint fee --- mutiny-core/src/lib.rs | 56 ++++++++++++++++++++++++++++++++++++++++++ mutiny-wasm/src/lib.rs | 13 ++++++++++ 2 files changed, 69 insertions(+) diff --git a/mutiny-core/src/lib.rs b/mutiny-core/src/lib.rs index 28a69db1c..ea03ca6c5 100644 --- a/mutiny-core/src/lib.rs +++ b/mutiny-core/src/lib.rs @@ -1071,6 +1071,62 @@ impl MutinyWallet { } } + /// Estimates the lightning fee for a transaction. Amount is either from the invoice + /// if one is available or a passed in amount (priority). It will try to predict either + /// sending the payment through a federation or through lightning, depending on balances. + /// The amount and fee is in satoshis. + /// Returns None if it has no good way to calculate fee. + pub async fn estimate_ln_fee( + &self, + inv: Option<&Bolt11Invoice>, + amt_sats: Option, + ) -> Result, MutinyError> { + let amt = if amt_sats.is_some() { + amt_sats.unwrap() + } else if inv.is_some() { + inv.unwrap().amount_milli_satoshis().expect("just checked") + } else { + return Err(MutinyError::BadAmountError); + }; + + // check balances first + let total_balances = self.get_balance().await?; + if total_balances.federation > amt { + let federation_ids = self.list_federation_ids().await?; + for federation_id in federation_ids { + // Check if the federation has enough balance + if let Some(fedimint_client) = self.federations.read().await.get(&federation_id) { + let current_balance = fedimint_client.get_balance().await?; + log_info!( + self.logger, + "current fedimint client balance: {}", + current_balance + ); + + let fees = fedimint_client.gateway_fee().await?; + let max_spendable = max_spendable_amount(current_balance, fees.clone()) + .map_or(Err(MutinyError::InsufficientBalance), Ok)?; + + if max_spendable >= amt { + let prop_fee_msat = + (amt as f64 * 1_000.0 * fees.proportional_millionths as f64) + / 1_000_000.0; + + let total_fee = fees.base_msat as f64 + prop_fee_msat; + return Ok(Some((total_fee / 1_000.0).floor() as u64)); + } + } + } + } + + if total_balances.lightning > amt { + // TODO try something to try to get lightning fee + return Ok(None); + } + + Err(MutinyError::InsufficientBalance) + } + /// Creates a BIP 21 invoice. This creates a new address and a lightning invoice. /// The lightning invoice may return errors related to the LSP. Check the error and /// fallback to `get_new_address` and warn the user that Lightning is not available. diff --git a/mutiny-wasm/src/lib.rs b/mutiny-wasm/src/lib.rs index 552cb951a..45bd39425 100644 --- a/mutiny-wasm/src/lib.rs +++ b/mutiny-wasm/src/lib.rs @@ -608,6 +608,19 @@ impl MutinyWallet { .estimate_sweep_channel_open_fee(fee_rate)?) } + /// Estimates the lightning fee for a transaction. Amount is either from the invoice + /// if one is available or a passed in amount (priority). It will try to predict either + /// sending the payment through a federation or through lightning, depending on balances. + /// The amount and fee is in satoshis. + /// Returns None if it has no good way to calculate fee. + pub async fn estimate_ln_fee( + &self, + inv: Option<&Bolt11Invoice>, + amt_sats: Option, + ) -> Result, MutinyJsError> { + Ok(self.inner.estimate_ln_fee(inv, amt_sats)?) + } + /// Bumps the given transaction by replacing the given tx with a transaction at /// the new given fee rate in sats/vbyte pub async fn bump_fee(&self, txid: String, fee_rate: f32) -> Result {