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

expose reverse swap fees #1127

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions libs/sdk-bindings/src/breez_sdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ dictionary PrepareOnchainPaymentResponse {
f64 fees_percentage;
u64 fees_lockup;
u64 fees_claim;

u64 fees_service;
Copy link
Contributor

@ok300 ok300 Nov 27, 2024

Choose a reason for hiding this comment

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

fees_percentage above and the new fees_service refer to the same thing. Wouldn't one have to go, to avoid confusing the user?

u64 sender_amount_sat;
u64 recipient_amount_sat;
u64 total_fees;
Expand All @@ -615,6 +615,10 @@ dictionary ReverseSwapInfo {
string? claim_txid;
u64 onchain_amount_sat;
ReverseSwapStatus status;
u64 fees_lockup;
u64 fees_claim;
u64 fees_service;
u64 total_fees;
Copy link
Contributor

Choose a reason for hiding this comment

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

To keep with the other 3 new fields, maybe fees_total is better?

};

dictionary BitcoinAddressData {
Expand Down Expand Up @@ -791,26 +795,11 @@ dictionary SendPaymentResponse {
Payment payment;
};

dictionary MaxReverseSwapAmountResponse {
u64 total_sat;
};

dictionary SendOnchainRequest {
u64 amount_sat;
string onchain_recipient_address;
string pair_hash;
u32 sat_per_vbyte;
};

dictionary PayOnchainRequest {
string recipient_address;
PrepareOnchainPaymentResponse prepare_res;
};

dictionary SendOnchainResponse {
ReverseSwapInfo reverse_swap_info;
};

dictionary PayOnchainResponse {
ReverseSwapInfo reverse_swap_info;
};
Expand Down Expand Up @@ -964,18 +953,9 @@ interface BlockingBreezServices {
[Throws=SdkError]
sequence<ReverseSwapInfo> in_progress_onchain_payments();

[Throws=SdkError]
sequence<ReverseSwapInfo> in_progress_reverse_swaps();

[Throws=SdkError]
void claim_reverse_swap(string lockup_address);

[Throws=SdkError]
MaxReverseSwapAmountResponse max_reverse_swap_amount();

[Throws=SendOnchainError]
SendOnchainResponse send_onchain(SendOnchainRequest req);

[Throws=SendOnchainError]
PayOnchainResponse pay_onchain(PayOnchainRequest req);

Expand Down
49 changes: 15 additions & 34 deletions libs/sdk-bindings/src/uniffi_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,21 @@ use breez_sdk_core::{
LnPaymentDetails, LnUrlAuthError, LnUrlAuthRequestData, LnUrlCallbackStatus, LnUrlErrorData,
LnUrlPayError, LnUrlPayErrorData, LnUrlPayRequest, LnUrlPayRequestData, LnUrlWithdrawError,
LnUrlWithdrawRequest, LnUrlWithdrawRequestData, LnUrlWithdrawResult, LnUrlWithdrawSuccessData,
LocaleOverrides, LocalizedName, LogEntry, LogStream, LspInformation,
MaxReverseSwapAmountResponse, MessageSuccessActionData, MetadataFilter, MetadataItem, Network,
NodeConfig, NodeCredentials, NodeState, OnchainPaymentLimitsResponse, OpenChannelFeeRequest,
OpenChannelFeeResponse, OpeningFeeParams, OpeningFeeParamsMenu, PayOnchainRequest,
PayOnchainResponse, Payment, PaymentDetails, PaymentFailedData, PaymentStatus, PaymentType,
PaymentTypeFilter, PrepareOnchainPaymentRequest, PrepareOnchainPaymentResponse,
PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse, PrepareRefundRequest,
PrepareRefundResponse, Rate, ReceiveOnchainRequest, ReceivePaymentRequest,
ReceivePaymentResponse, RecommendedFees, RedeemOnchainFundsRequest, RedeemOnchainFundsResponse,
RefundRequest, RefundResponse, ReportIssueRequest, ReportPaymentFailureDetails,
ReverseSwapFeesRequest, ReverseSwapInfo, ReverseSwapPairInfo, ReverseSwapStatus, RouteHint,
RouteHintHop, SendOnchainRequest, SendOnchainResponse, SendPaymentRequest, SendPaymentResponse,
SendSpontaneousPaymentRequest, ServiceHealthCheckResponse, SignMessageRequest,
SignMessageResponse, StaticBackupRequest, StaticBackupResponse, SuccessActionProcessed,
SwapAmountType, SwapInfo, SwapStatus, Symbol, TlvEntry, UnspentTransactionOutput,
UrlSuccessActionData,
LocaleOverrides, LocalizedName, LogEntry, LogStream, LspInformation, MessageSuccessActionData,
MetadataFilter, MetadataItem, Network, NodeConfig, NodeCredentials, NodeState,
OnchainPaymentLimitsResponse, OpenChannelFeeRequest, OpenChannelFeeResponse, OpeningFeeParams,
OpeningFeeParamsMenu, PayOnchainRequest, PayOnchainResponse, Payment, PaymentDetails,
PaymentFailedData, PaymentStatus, PaymentType, PaymentTypeFilter, PrepareOnchainPaymentRequest,
PrepareOnchainPaymentResponse, PrepareRedeemOnchainFundsRequest,
PrepareRedeemOnchainFundsResponse, PrepareRefundRequest, PrepareRefundResponse, Rate,
ReceiveOnchainRequest, ReceivePaymentRequest, ReceivePaymentResponse, RecommendedFees,
RedeemOnchainFundsRequest, RedeemOnchainFundsResponse, RefundRequest, RefundResponse,
ReportIssueRequest, ReportPaymentFailureDetails, ReverseSwapFeesRequest, ReverseSwapInfo,
ReverseSwapPairInfo, ReverseSwapStatus, RouteHint, RouteHintHop, SendPaymentRequest,
SendPaymentResponse, SendSpontaneousPaymentRequest, ServiceHealthCheckResponse,
SignMessageRequest, SignMessageResponse, StaticBackupRequest, StaticBackupResponse,
SuccessActionProcessed, SwapAmountType, SwapInfo, SwapStatus, Symbol, TlvEntry,
UnspentTransactionOutput, UrlSuccessActionData,
};
use log::{Level, LevelFilter, Metadata, Record};
use once_cell::sync::{Lazy, OnceCell};
Expand Down Expand Up @@ -332,28 +331,10 @@ impl BlockingBreezServices {
rt().block_on(self.breez_services.in_progress_onchain_payments())
}

pub fn in_progress_reverse_swaps(&self) -> SdkResult<Vec<ReverseSwapInfo>> {
#[allow(deprecated)]
rt().block_on(self.breez_services.in_progress_reverse_swaps())
}

pub fn claim_reverse_swap(&self, lockup_address: String) -> SdkResult<()> {
rt().block_on(self.breez_services.claim_reverse_swap(lockup_address))
}

pub fn max_reverse_swap_amount(&self) -> SdkResult<MaxReverseSwapAmountResponse> {
#[allow(deprecated)]
rt().block_on(self.breez_services.max_reverse_swap_amount())
}

pub fn send_onchain(
&self,
req: SendOnchainRequest,
) -> Result<SendOnchainResponse, SendOnchainError> {
#[allow(deprecated)]
rt().block_on(self.breez_services.send_onchain(req))
}

pub fn pay_onchain(
&self,
req: PayOnchainRequest,
Expand Down
42 changes: 8 additions & 34 deletions libs/sdk-core/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ use crate::models::{Config, LogEntry, NodeState, Payment, SwapInfo};
use crate::{
BackupStatus, BuyBitcoinRequest, BuyBitcoinResponse, CheckMessageRequest, CheckMessageResponse,
ConfigureNodeRequest, ConnectRequest, EnvironmentType, ListPaymentsRequest, ListSwapsRequest,
LnUrlAuthError, MaxReverseSwapAmountResponse, NodeConfig, NodeCredentials,
OnchainPaymentLimitsResponse, OpenChannelFeeRequest, OpenChannelFeeResponse, PayOnchainRequest,
PayOnchainResponse, PrepareOnchainPaymentRequest, PrepareOnchainPaymentResponse,
PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse, PrepareRefundRequest,
PrepareRefundResponse, ReceiveOnchainRequest, ReceivePaymentRequest, ReceivePaymentResponse,
LnUrlAuthError, NodeConfig, NodeCredentials, OnchainPaymentLimitsResponse,
OpenChannelFeeRequest, OpenChannelFeeResponse, PayOnchainRequest, PayOnchainResponse,
PrepareOnchainPaymentRequest, PrepareOnchainPaymentResponse, PrepareRedeemOnchainFundsRequest,
PrepareRedeemOnchainFundsResponse, PrepareRefundRequest, PrepareRefundResponse,
ReceiveOnchainRequest, ReceivePaymentRequest, ReceivePaymentResponse,
RedeemOnchainFundsRequest, RedeemOnchainFundsResponse, RefundRequest, RefundResponse,
ReportIssueRequest, ReverseSwapFeesRequest, ReverseSwapInfo, ReverseSwapPairInfo,
SendOnchainRequest, SendOnchainResponse, SendPaymentRequest, SendPaymentResponse,
SendSpontaneousPaymentRequest, ServiceHealthCheckResponse, SignMessageRequest,
SignMessageResponse, StaticBackupRequest, StaticBackupResponse,
SendPaymentRequest, SendPaymentResponse, SendSpontaneousPaymentRequest,
ServiceHealthCheckResponse, SignMessageRequest, SignMessageResponse, StaticBackupRequest,
StaticBackupResponse,
};

// === FRB mirroring
Expand Down Expand Up @@ -601,20 +601,6 @@ pub fn list_fiat_currencies() -> Result<Vec<FiatCurrency>> {

/* On-Chain Swap API's */

/// See [BreezServices::max_reverse_swap_amount]
pub fn max_reverse_swap_amount() -> Result<MaxReverseSwapAmountResponse> {
#[allow(deprecated)]
block_on(async { get_breez_services().await?.max_reverse_swap_amount().await })
.map_err(anyhow::Error::new::<SdkError>)
}

/// See [BreezServices::send_onchain]
pub fn send_onchain(req: SendOnchainRequest) -> Result<SendOnchainResponse> {
#[allow(deprecated)]
block_on(async { get_breez_services().await?.send_onchain(req).await })
.map_err(anyhow::Error::new::<SendOnchainError>)
}

/// See [BreezServices::pay_onchain]
pub fn pay_onchain(req: PayOnchainRequest) -> Result<PayOnchainResponse> {
block_on(async { get_breez_services().await?.pay_onchain(req).await })
Expand Down Expand Up @@ -698,18 +684,6 @@ pub fn list_swaps(req: ListSwapsRequest) -> Result<Vec<SwapInfo>> {
.map_err(anyhow::Error::new::<SdkError>)
}

/// See [BreezServices::in_progress_reverse_swaps]
pub fn in_progress_reverse_swaps() -> Result<Vec<ReverseSwapInfo>> {
#[allow(deprecated)]
block_on(async {
get_breez_services()
.await?
.in_progress_reverse_swaps()
.await
})
.map_err(anyhow::Error::new::<SdkError>)
}

/// See [BreezServices::claim_reverse_swap]
pub fn claim_reverse_swap(lockup_address: String) -> Result<()> {
block_on(async {
Expand Down
89 changes: 32 additions & 57 deletions libs/sdk-core/src/breez_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use crate::node_api::{CreateInvoiceRequest, NodeAPI};
use crate::persist::db::SqliteStorage;
use crate::swap_in::swap::BTCReceiveSwap;
use crate::swap_out::boltzswap::BoltzApi;
use crate::swap_out::reverseswap::{BTCSendSwap, CreateReverseSwapArg};
use crate::swap_out::reverseswap::BTCSendSwap;
use crate::*;

const DETECT_HIBERNATE_SLEEP_DURATION: Duration = Duration::from_secs(1);
Expand Down Expand Up @@ -935,14 +935,12 @@ impl BreezServices {

Ok(res)
}

/// Returns the max amount that can be sent on-chain using the send_onchain method.
/// The returned amount is the sum of the max amount that can be sent on each channel
/// minus the expected fees.
/// This is possible since the route to the swapper node is known in advance and is expected
/// to consist of maximum 3 hops.
#[deprecated(note = "use onchain_payment_limits instead")]
pub async fn max_reverse_swap_amount(&self) -> SdkResult<MaxReverseSwapAmountResponse> {
async fn max_reverse_swap_amount(&self) -> SdkResult<u64> {
// fetch the last hop hints from the swapper
let last_hop = self.btc_send_swapper.last_hop_for_payment().await?;
info!("max_reverse_swap_amount last_hop={:?}", last_hop);
Expand All @@ -965,36 +963,7 @@ impl BreezServices {
// Sum the max amount per channel and return the result
let total_msat: u64 = max_to_pay.into_iter().map(|m| m.amount_msat).sum();
let total_sat = total_msat / 1000;
Ok(MaxReverseSwapAmountResponse { total_sat })
}

/// Creates a reverse swap and attempts to pay the HODL invoice
#[deprecated(note = "use pay_onchain instead")]
pub async fn send_onchain(
&self,
req: SendOnchainRequest,
) -> Result<SendOnchainResponse, SendOnchainError> {
let reverse_swap_info = self
.pay_onchain_common(CreateReverseSwapArg::V1(req))
.await?;
Ok(SendOnchainResponse { reverse_swap_info })
}

/// Returns the blocking [ReverseSwapInfo]s that are in progress
#[deprecated(note = "use in_progress_onchain_payments instead")]
pub async fn in_progress_reverse_swaps(&self) -> SdkResult<Vec<ReverseSwapInfo>> {
let full_rsis = self.btc_send_swapper.list_blocking().await?;

let mut rsis = vec![];
for full_rsi in full_rsis {
let rsi = self
.btc_send_swapper
.convert_reverse_swap_info(full_rsi)
.await?;
rsis.push(rsi);
}

Ok(rsis)
Ok(total_sat)
}

/// list non-completed expired swaps that should be refunded by calling [BreezServices::refund]
Expand Down Expand Up @@ -1023,14 +992,13 @@ impl BreezServices {
pub async fn onchain_payment_limits(&self) -> SdkResult<OnchainPaymentLimitsResponse> {
let fee_info = self.btc_send_swapper.fetch_reverse_swap_fees().await?;
debug!("Reverse swap pair info: {fee_info:?}");
#[allow(deprecated)]
let max_amt_current_channels = self.max_reverse_swap_amount().await?;
debug!("Max send amount possible with current channels: {max_amt_current_channels:?}");

Ok(OnchainPaymentLimitsResponse {
min_sat: fee_info.min,
max_sat: fee_info.max,
max_payable_sat: max_amt_current_channels.total_sat,
max_payable_sat: max_amt_current_channels,
})
}

Expand All @@ -1053,8 +1021,7 @@ impl BreezServices {
// Calculate (send_amt, recv_amt) from the inputs and fees
let fees_lockup = fee_info.fees_lockup;
let p = fee_info.fees_percentage;
let fees_claim = BTCSendSwap::calculate_claim_tx_fee(req.claim_tx_feerate)?;
let (send_amt, recv_amt) = match req.amount_type {
let (send_amt, recv_amt, fees_service) = match req.amount_type {
SwapAmountType::Send => {
let temp_send_amt = req.amount_sat;
let service_fees = swap_out::get_service_fee_sat(temp_send_amt, p);
Expand All @@ -1066,14 +1033,14 @@ impl BreezServices {
)
);

(temp_send_amt, temp_send_amt - total_fees)
(temp_send_amt, temp_send_amt - total_fees, service_fees)
}
SwapAmountType::Receive => {
let temp_recv_amt = req.amount_sat;
let send_amt_minus_service_fee = temp_recv_amt + fees_lockup + fees_claim;
let temp_send_amt = swap_out::get_invoice_amount_sat(send_amt_minus_service_fee, p);

(temp_send_amt, temp_recv_amt)
let service_fees = temp_send_amt - send_amt_minus_service_fee;
(temp_send_amt, temp_recv_amt, service_fees)
}
};

Expand All @@ -1085,15 +1052,14 @@ impl BreezServices {
fees_percentage: p,
fees_lockup,
fees_claim,
fees_service,
sender_amount_sat: send_amt,
recipient_amount_sat: recv_amt,
total_fees: send_amt - recv_amt,
})
}

/// Creates a reverse swap and attempts to pay the HODL invoice
///
/// Supersedes [BreezServices::send_onchain]
pub async fn pay_onchain(
&self,
req: PayOnchainRequest,
Expand All @@ -1103,16 +1069,9 @@ impl BreezServices {
SendOnchainError::generic("Send amount must be bigger than receive amount")
);

let reverse_swap_info = self
.pay_onchain_common(CreateReverseSwapArg::V2(req))
.await?;
Ok(PayOnchainResponse { reverse_swap_info })
}

async fn pay_onchain_common(&self, req: CreateReverseSwapArg) -> SdkResult<ReverseSwapInfo> {
ensure_sdk!(self.in_progress_onchain_payments().await?.is_empty(), SdkError::Generic { err:
ensure_sdk!(self.in_progress_onchain_payments().await?.is_empty(), SendOnchainError::Generic { err:
"You can only start a new one after after the ongoing ones finish. \
Use the in_progress_reverse_swaps method to get an overview of currently ongoing reverse swaps".into(),
Use the in_progress_onchain_payments method to get an overview of currently ongoing reverse swaps".into(),
});

let full_rsi = self.btc_send_swapper.create_reverse_swap(req).await?;
Expand All @@ -1130,15 +1089,23 @@ impl BreezServices {
self.register_onchain_tx_notification(address, &webhook_url)
.await?;
}
Ok(reverse_swap_info)
Ok(PayOnchainResponse { reverse_swap_info })
}

/// Returns the blocking [ReverseSwapInfo]s that are in progress.
///
/// Supersedes [BreezServices::in_progress_reverse_swaps]
pub async fn in_progress_onchain_payments(&self) -> SdkResult<Vec<ReverseSwapInfo>> {
#[allow(deprecated)]
self.in_progress_reverse_swaps().await
let full_rsis = self.btc_send_swapper.list_blocking().await?;

let mut rsis = vec![];
for full_rsi in full_rsis {
let rsi = self
.btc_send_swapper
.convert_reverse_swap_info(full_rsi)
.await?;
rsis.push(rsi);
}

Ok(rsis)
}

/// Execute a command directly on the NodeAPI interface.
Expand Down Expand Up @@ -3054,6 +3021,10 @@ pub(crate) mod tests {
lockup_txid: Some("lockup_txid".to_string()),
claim_txid: Some("claim_txid".to_string()),
},
fees_lockup: 0,
fees_claim: 0,
fees_service: 0,
total_fees: 0,
};
let rev_swap_info = ReverseSwapInfo {
id: "rev_swap_id".to_string(),
Expand All @@ -3062,6 +3033,10 @@ pub(crate) mod tests {
claim_txid: Some("claim_txid".to_string()),
onchain_amount_sat: 250,
status: ReverseSwapStatus::CompletedConfirmed,
fees_claim: 0,
fees_lockup: 0,
fees_service: 0,
total_fees: 0,
};
let dummy_transactions = vec![
Payment {
Expand Down
Loading
Loading