Skip to content

Commit

Permalink
Add zero-amount Receive Chain Swap
Browse files Browse the repository at this point in the history
  • Loading branch information
ok300 committed Oct 29, 2024
1 parent 414c9f1 commit 89e20d4
Showing 1 changed file with 33 additions and 27 deletions.
60 changes: 33 additions & 27 deletions lib/core/src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,10 +633,12 @@ impl LiquidSdk {
fn get_and_validate_chain_pair(
&self,
direction: Direction,
user_lockup_amount_sat: u64,
user_lockup_amount_sat: Option<u64>,
) -> Result<ChainPair, PaymentError> {
let pair = self.get_chain_pair(direction)?;
self.validate_user_lockup_amount_for_chain_pair(&pair, user_lockup_amount_sat)?;
if let Some(user_lockup_amount_sat) = user_lockup_amount_sat {
self.validate_user_lockup_amount_for_chain_pair(&pair, user_lockup_amount_sat)?;
}
Ok(pair)
}

Expand Down Expand Up @@ -1442,24 +1444,22 @@ impl LiquidSdk {
);
}
PaymentMethod::BitcoinAddress => {
let Some(payer_amount_sat) = req.payer_amount_sat else {
return Err(PaymentError::AmountMissing { err: "`payer_amount_sat` must be specified when `PaymentMethod::BitcoinAddress` is used.".to_string() });
};
let payer_amount_sat = req.payer_amount_sat;
let pair =
self.get_and_validate_chain_pair(Direction::Incoming, payer_amount_sat)?;
let claim_fees_sat = pair.fees.claim_estimate();
let server_fees_sat = pair.fees.server();
fees_sat = pair.fees.boltz(payer_amount_sat) + claim_fees_sat + server_fees_sat;
debug!(
"Preparing Chain Receive Swap with: payer_amount_sat {payer_amount_sat} sat, fees_sat {fees_sat} sat"
);
let service_fees_sat = payer_amount_sat
.map(|user_lockup_amount_sat| pair.fees.boltz(user_lockup_amount_sat))
.unwrap_or_default();

fees_sat = service_fees_sat + claim_fees_sat + server_fees_sat;
debug!("Preparing Chain Receive Swap with: payer_amount_sat {payer_amount_sat:?}, fees_sat {fees_sat}");
}
PaymentMethod::LiquidAddress => {
fees_sat = 0;
debug!(
"Preparing Liquid Receive Swap with: amount_sat {:?} sat, fees_sat {fees_sat} sat",
req.payer_amount_sat
);
let payer_amount_sat = req.payer_amount_sat;
debug!("Preparing Liquid Receive Swap with: amount_sat {payer_amount_sat:?}, fees_sat {fees_sat}");
}
};

Expand Down Expand Up @@ -1519,12 +1519,7 @@ impl LiquidSdk {
self.create_receive_swap(*amount_sat, *fees_sat, description, description_hash)
.await
}
PaymentMethod::BitcoinAddress => {
let Some(amount_sat) = amount_sat else {
return Err(PaymentError::AmountMissing { err: "`amount_sat` must be specified when `PaymentMethod::BitcoinAddress` is used.".to_string() });
};
self.receive_onchain(*amount_sat, *fees_sat).await
}
PaymentMethod::BitcoinAddress => self.receive_onchain(*amount_sat, *fees_sat).await,
PaymentMethod::LiquidAddress => {
let address = self.onchain_wallet.next_unused_address().await?.to_string();

Expand Down Expand Up @@ -1671,15 +1666,19 @@ impl LiquidSdk {

async fn create_receive_chain_swap(
&self,
user_lockup_amount_sat: u64,
user_lockup_amount_sat: Option<u64>,
fees_sat: u64,
) -> Result<ChainSwap, PaymentError> {
let pair = self.get_and_validate_chain_pair(Direction::Incoming, user_lockup_amount_sat)?;
let claim_fees_sat = pair.fees.claim_estimate();
let server_fees_sat = pair.fees.server();
// Service fees are 0 if this is a zero-amount swap
let service_fees_sat = user_lockup_amount_sat
.map(|user_lockup_amount_sat| pair.fees.boltz(user_lockup_amount_sat))
.unwrap_or_default();

ensure_sdk!(
fees_sat == pair.fees.boltz(user_lockup_amount_sat) + claim_fees_sat + server_fees_sat,
fees_sat == service_fees_sat + claim_fees_sat + server_fees_sat,
PaymentError::InvalidOrExpiredFees
);

Expand Down Expand Up @@ -1711,7 +1710,7 @@ impl LiquidSdk {
preimage_hash: preimage.sha256,
claim_public_key: Some(claim_public_key),
refund_public_key: Some(refund_public_key),
user_lock_amount: Some(user_lockup_amount_sat),
user_lock_amount: user_lockup_amount_sat,
server_lock_amount: None,
pair_hash: Some(pair.hash),
referral_id: None,
Expand All @@ -1722,8 +1721,12 @@ impl LiquidSdk {
let create_response_json =
ChainSwap::from_boltz_struct_to_json(&create_response, &swap_id)?;

let accept_zero_conf = user_lockup_amount_sat <= pair.limits.maximal_zero_conf;
let receiver_amount_sat = user_lockup_amount_sat - fees_sat;
let accept_zero_conf = user_lockup_amount_sat
.map(|user_lockup_amount_sat| user_lockup_amount_sat <= pair.limits.maximal_zero_conf)
.unwrap_or(false);
let receiver_amount_sat = user_lockup_amount_sat
.map(|user_lockup_amount_sat| user_lockup_amount_sat - fees_sat)
.unwrap_or(0);
let claim_address = self.onchain_wallet.next_unused_address().await?.to_string();

let swap = ChainSwap {
Expand All @@ -1734,7 +1737,7 @@ impl LiquidSdk {
timeout_block_height: create_response.lockup_details.timeout_block_height,
preimage: preimage_str,
description: Some("Bitcoin transfer".to_string()),
payer_amount_sat: user_lockup_amount_sat,
payer_amount_sat: user_lockup_amount_sat.unwrap_or(0),
receiver_amount_sat,
claim_fees_sat,
accept_zero_conf,
Expand All @@ -1754,9 +1757,12 @@ impl LiquidSdk {
}

/// Receive from a Bitcoin transaction via a chain swap.
///
/// If no `user_lockup_amount_sat` is specified, this is an amountless swap and `fees_sat` exclude
/// the service fees.
async fn receive_onchain(
&self,
payer_amount_sat: u64,
payer_amount_sat: Option<u64>,
fees_sat: u64,
) -> Result<ReceivePaymentResponse, PaymentError> {
self.ensure_is_started().await?;
Expand Down Expand Up @@ -1924,7 +1930,7 @@ impl LiquidSdk {
pub async fn buy_bitcoin(&self, req: &BuyBitcoinRequest) -> Result<String, PaymentError> {
let swap = self
.create_receive_chain_swap(
req.prepare_response.amount_sat,
Some(req.prepare_response.amount_sat),
req.prepare_response.fees_sat,
)
.await?;
Expand Down

0 comments on commit 89e20d4

Please sign in to comment.