mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2026-01-08 08:34:21 +01:00
Allow resending to timeouted swaps
This commit is contained in:
@@ -9,14 +9,12 @@ use std::{
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use boltz_client::lightning_invoice::Bolt11InvoiceDescription;
|
||||
use boltz_client::network::Chain;
|
||||
use boltz_client::swaps::boltzv2;
|
||||
use boltz_client::ToHex;
|
||||
use boltz_client::{
|
||||
swaps::{
|
||||
boltz::{RevSwapStates, SubSwapStates},
|
||||
boltzv2::*,
|
||||
liquidv2::LBtcSwapTxV2,
|
||||
boltzv2::*,
|
||||
},
|
||||
util::secrets::Preimage,
|
||||
Amount, Bolt11Invoice, ElementsAddress, LBtcSwapScriptV2,
|
||||
@@ -204,19 +202,28 @@ impl LiquidSdk {
|
||||
tokio::select! {
|
||||
update = updates_stream.recv() => match update {
|
||||
Ok(boltzv2::Update { id, status }) => {
|
||||
let _ = cloned.sync().await;
|
||||
|
||||
if let Ok(_) = cloned.try_handle_send_swap_boltz_status(&status, &id).await
|
||||
{
|
||||
info!("Handled send swap update");
|
||||
} else if let Ok(_) = cloned
|
||||
.try_handle_receive_swap_boltz_status(&status, &id)
|
||||
.await
|
||||
{
|
||||
info!("Handled receive swap update");
|
||||
} else {
|
||||
warn!("Unhandled swap {id}: {status}")
|
||||
}
|
||||
let _ = cloned.sync().await;
|
||||
match cloned.persister.fetch_send_swap_by_id(&id) {
|
||||
Ok(_) => {
|
||||
match cloned.try_handle_send_swap_boltz_status(&status, &id).await {
|
||||
Ok(_) => info!("Succesfully handled Send Swap {id} update"),
|
||||
Err(e) => error!("Failed to handle Send Swap {id} update: {e}")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match cloned.persister.fetch_receive_swap(&id) {
|
||||
Ok(Some(_)) => {
|
||||
match cloned.try_handle_receive_swap_boltz_status(&status, &id).await {
|
||||
Ok(_) => info!("Succesfully handled Receive Swap {id} update"),
|
||||
Err(e) => error!("Failed to handle Receive Swap {id} update: {e}")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Could not find Swap {id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Received stream error: {e:?}"),
|
||||
},
|
||||
@@ -563,7 +570,7 @@ impl LiquidSdk {
|
||||
ongoing_send_swap.state,
|
||||
ongoing_send_swap.lockup_tx_id.clone(),
|
||||
) {
|
||||
(PaymentState::Created, None) => {
|
||||
(PaymentState::Created, None) | (PaymentState::TimedOut, None) => {
|
||||
let create_response = ongoing_send_swap.get_boltz_create_response()?;
|
||||
let lockup_tx_id = self.lockup_funds(id, &create_response).await?;
|
||||
|
||||
@@ -601,7 +608,10 @@ impl LiquidSdk {
|
||||
Ok(SubSwapStates::TransactionClaimPending) => {
|
||||
self.cooperate_send_swap_claim(&ongoing_send_swap)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Could not post claim details. Err: {e:?}"))?;
|
||||
.map_err(|e| {
|
||||
error!("Could not cooperate Send Swap {id} claim: {e}");
|
||||
anyhow!("Could not post claim details. Err: {e:?}")
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -612,6 +622,8 @@ impl LiquidSdk {
|
||||
self.get_preimage_from_script_path_claim_spend(&ongoing_send_swap)?;
|
||||
self.validate_send_swap_preimage(id, &ongoing_send_swap.invoice, &preimage)
|
||||
.await?;
|
||||
self.try_handle_send_swap_update(id, Complete, Some(&preimage), None, None)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -729,16 +741,6 @@ impl LiquidSdk {
|
||||
}
|
||||
}
|
||||
|
||||
fn network_config(&self) -> ElectrumConfig {
|
||||
ElectrumConfig::new(
|
||||
self.network.into(),
|
||||
&self.electrum_url.to_string(),
|
||||
true,
|
||||
true,
|
||||
100,
|
||||
)
|
||||
}
|
||||
|
||||
async fn build_tx(
|
||||
&self,
|
||||
fee_rate: Option<f32>,
|
||||
@@ -854,22 +856,6 @@ impl LiquidSdk {
|
||||
.ok_or(PaymentError::InvalidPreimage)
|
||||
}
|
||||
|
||||
async fn new_refund_tx(
|
||||
&self,
|
||||
swap_id: &str,
|
||||
swap_script: &LBtcSwapScriptV2,
|
||||
) -> Result<LBtcSwapTxV2, PaymentError> {
|
||||
let output_address = self.next_unused_address().await?.to_string();
|
||||
let network_config = self.config.get_electrum_config();
|
||||
Ok(LBtcSwapTxV2::new_refund(
|
||||
swap_script.clone(),
|
||||
&output_address,
|
||||
&network_config,
|
||||
self.config.clone().boltz_url,
|
||||
swap_id.to_string(),
|
||||
)?)
|
||||
}
|
||||
|
||||
async fn try_refund_non_cooperative(
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
@@ -896,9 +882,7 @@ impl LiquidSdk {
|
||||
Ok(refund_tx_id)
|
||||
}
|
||||
|
||||
async fn try_refund(&self, swap: &SendSwap) -> Result<String, PaymentError> {
|
||||
let swap_script = swap.get_swap_script()?;
|
||||
let refund_tx = self.new_refund_tx(&swap.id, &swap_script).await?;
|
||||
async fn try_refund(&self, swap: &SendSwap) -> Result<String, PaymentError> {
|
||||
let amount_sat = get_invoice_amount!(swap.invoice);
|
||||
let broadcast_fees_sat =
|
||||
Amount::from_sat(self.get_broadcast_fee_estimation(amount_sat).await?);
|
||||
@@ -926,8 +910,7 @@ impl LiquidSdk {
|
||||
) -> Result<(), PaymentError> {
|
||||
Self::verify_payment_hash(preimage, invoice)?;
|
||||
info!("Preimage is valid for Send Swap {swap_id}");
|
||||
self.try_handle_send_swap_update(swap_id, Complete, Some(preimage), None, None)
|
||||
.await
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Interact with Boltz to assist in them doing a cooperative claim
|
||||
@@ -936,7 +919,10 @@ impl LiquidSdk {
|
||||
"Claim is pending for Send Swap {}. Initiating cooperative claim",
|
||||
&send_swap.id
|
||||
);
|
||||
self.swapper.claim_send_swap_cooperative(send_swap)?;
|
||||
let output_address = self.next_unused_address().await?.to_string();
|
||||
let preimage = self.swapper.claim_send_swap_cooperative(send_swap, &output_address)?;
|
||||
self.try_handle_send_swap_update(&send_swap.id, Complete, Some(&preimage), None, None)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1030,6 +1016,7 @@ impl LiquidSdk {
|
||||
swap
|
||||
}
|
||||
};
|
||||
self.status_stream.track_swap_id(&swap.id)?;
|
||||
|
||||
let accept_zero_conf = swap.get_boltz_create_response()?.accept_zero_conf;
|
||||
self.wait_for_payment(swap.id, accept_zero_conf)
|
||||
@@ -1309,6 +1296,7 @@ impl LiquidSdk {
|
||||
.ok_or_else(|| anyhow!("Found no input for claim tx"))?;
|
||||
|
||||
let script_witness_bytes = input.clone().witness.script_witness;
|
||||
info!("Found Send Swap {id} claim tx witness: {script_witness_bytes:?}");
|
||||
let script_witness = Witness::from(script_witness_bytes);
|
||||
|
||||
let preimage_bytes = script_witness
|
||||
|
||||
@@ -36,7 +36,7 @@ pub trait Swapper: Send + Sync {
|
||||
fn refund_send_swap_cooperative(
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
output_address: &String,
|
||||
output_address: &str,
|
||||
broadcast_fees_sat: Amount,
|
||||
) -> Result<String, PaymentError>;
|
||||
|
||||
@@ -45,13 +45,17 @@ pub trait Swapper: Send + Sync {
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
broadcast_fees_sat: Amount,
|
||||
output_address: &String,
|
||||
output_address: &str,
|
||||
current_height: u32,
|
||||
) -> Result<String, PaymentError>;
|
||||
|
||||
/// Claim send swap cooperatively. Here the remote swapper is the one that claims.
|
||||
/// We are helping to use key spend path for cheaper fees.
|
||||
fn claim_send_swap_cooperative(&self, swap: &SendSwap) -> Result<(), PaymentError>;
|
||||
fn claim_send_swap_cooperative(
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
output_address: &str,
|
||||
) -> Result<String, PaymentError>;
|
||||
|
||||
// Create a new receive swap
|
||||
fn create_receive_swap(
|
||||
@@ -70,7 +74,7 @@ pub trait Swapper: Send + Sync {
|
||||
) -> Result<String, PaymentError>;
|
||||
|
||||
// chain broadcast
|
||||
fn broadcast_tx(&self, chain: Chain, tx_hex: &String) -> Result<Value, PaymentError>;
|
||||
fn broadcast_tx(&self, chain: Chain, tx_hex: &str) -> Result<Value, PaymentError>;
|
||||
}
|
||||
|
||||
pub struct BoltzSwapper {
|
||||
@@ -161,16 +165,12 @@ impl Swapper for BoltzSwapper {
|
||||
fn refund_send_swap_cooperative(
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
output_address: &String,
|
||||
output_address: &str,
|
||||
broadcast_fees_sat: Amount,
|
||||
) -> Result<String, PaymentError> {
|
||||
info!("Initiating cooperative refund for Send Swap {}", &swap.id);
|
||||
let create_response = swap
|
||||
.get_boltz_create_response()
|
||||
.map_err(|e| Error::Generic(e.to_string()))?;
|
||||
|
||||
let refund_keypair = swap.get_refund_keypair()?;
|
||||
let refund_tx = self.new_refund_tx(swap, &refund_keypair, output_address)?;
|
||||
let refund_tx = self.new_refund_tx(swap, &refund_keypair, &output_address.into())?;
|
||||
|
||||
let cooperative = Some((&self.client, &swap.id));
|
||||
let tx = refund_tx.sign_refund(
|
||||
@@ -197,7 +197,7 @@ impl Swapper for BoltzSwapper {
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
broadcast_fees_sat: Amount,
|
||||
output_address: &String,
|
||||
output_address: &str,
|
||||
current_height: u32,
|
||||
) -> Result<String, PaymentError> {
|
||||
let keypair = swap.get_refund_keypair()?;
|
||||
@@ -228,7 +228,7 @@ impl Swapper for BoltzSwapper {
|
||||
});
|
||||
}
|
||||
|
||||
let refund_tx = self.new_refund_tx(swap, &keypair, output_address)?;
|
||||
let refund_tx = self.new_refund_tx(swap, &keypair, &output_address.into())?;
|
||||
let tx = refund_tx.sign_refund(
|
||||
&swap
|
||||
.get_refund_keypair()
|
||||
@@ -250,13 +250,17 @@ impl Swapper for BoltzSwapper {
|
||||
|
||||
/// Claim send swap cooperatively. Here the remote swapper is the one that claims.
|
||||
/// We are helping to use key spend path for cheaper fees.
|
||||
fn claim_send_swap_cooperative(&self, swap: &SendSwap) -> Result<(), PaymentError> {
|
||||
fn claim_send_swap_cooperative(
|
||||
&self,
|
||||
swap: &SendSwap,
|
||||
output_address: &str,
|
||||
) -> Result<String, PaymentError> {
|
||||
let swap_id = &swap.id;
|
||||
let keypair = swap.get_refund_keypair()?;
|
||||
let refund_tx = self.new_refund_tx(swap, &keypair, &"".into())?;
|
||||
let refund_tx = self.new_refund_tx(swap, &keypair, &output_address.into())?;
|
||||
|
||||
let claim_tx_response = self.client.get_claim_tx_details(&swap_id.to_string())?;
|
||||
debug!("Received claim tx details: {:?}", &claim_tx_response);
|
||||
info!("Received claim tx details: {:?}", &claim_tx_response);
|
||||
|
||||
self.validate_send_swap_preimage(swap_id, &swap.invoice, &claim_tx_response.preimage)?;
|
||||
|
||||
@@ -265,8 +269,8 @@ impl Swapper for BoltzSwapper {
|
||||
|
||||
self.client
|
||||
.post_claim_tx_details(&swap_id.to_string(), pub_nonce, partial_sig)?;
|
||||
debug!("Successfully sent claim details for swap-in {swap_id}");
|
||||
Ok(())
|
||||
info!("Successfully sent claim details for swap-in {swap_id}");
|
||||
Ok(claim_tx_response.preimage)
|
||||
}
|
||||
|
||||
// Create a new receive swap
|
||||
@@ -326,7 +330,7 @@ impl Swapper for BoltzSwapper {
|
||||
}
|
||||
|
||||
// chain broadcast
|
||||
fn broadcast_tx(&self, chain: Chain, tx_hex: &String) -> Result<Value, PaymentError> {
|
||||
Ok(self.client.broadcast_tx(chain, tx_hex)?)
|
||||
fn broadcast_tx(&self, chain: Chain, tx_hex: &str) -> Result<Value, PaymentError> {
|
||||
Ok(self.client.broadcast_tx(chain, &tx_hex.into())?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user