mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2026-02-20 13:34:26 +01:00
Cancel the created swap on timeout (#249)
* Cancel slow swap * Change Cancelled to TimedOut * Set Created send swaps to TimedOut on start
This commit is contained in:
@@ -132,6 +132,7 @@ enum PaymentState {
|
||||
"Pending",
|
||||
"Complete",
|
||||
"Failed",
|
||||
"TimedOut",
|
||||
};
|
||||
|
||||
[Enum]
|
||||
|
||||
@@ -431,6 +431,7 @@ impl CstDecode<crate::model::PaymentState> for i32 {
|
||||
1 => crate::model::PaymentState::Pending,
|
||||
2 => crate::model::PaymentState::Complete,
|
||||
3 => crate::model::PaymentState::Failed,
|
||||
4 => crate::model::PaymentState::TimedOut,
|
||||
_ => unreachable!("Invalid variant for PaymentState: {}", self),
|
||||
}
|
||||
}
|
||||
@@ -858,6 +859,7 @@ impl SseDecode for crate::model::PaymentState {
|
||||
1 => crate::model::PaymentState::Pending,
|
||||
2 => crate::model::PaymentState::Complete,
|
||||
3 => crate::model::PaymentState::Failed,
|
||||
4 => crate::model::PaymentState::TimedOut,
|
||||
_ => unreachable!("Invalid variant for PaymentState: {}", inner),
|
||||
};
|
||||
}
|
||||
@@ -1292,6 +1294,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::PaymentState {
|
||||
Self::Pending => 1.into_dart(),
|
||||
Self::Complete => 2.into_dart(),
|
||||
Self::Failed => 3.into_dart(),
|
||||
Self::TimedOut => 4.into_dart(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1789,6 +1792,7 @@ impl SseEncode for crate::model::PaymentState {
|
||||
crate::model::PaymentState::Pending => 1,
|
||||
crate::model::PaymentState::Complete => 2,
|
||||
crate::model::PaymentState::Failed => 3,
|
||||
crate::model::PaymentState::TimedOut => 4,
|
||||
_ => {
|
||||
unimplemented!("");
|
||||
}
|
||||
|
||||
@@ -378,6 +378,12 @@ pub enum PaymentState {
|
||||
///
|
||||
/// This is the status when a swap refund was initiated and the refund tx is confirmed.
|
||||
Failed = 3,
|
||||
|
||||
/// ## Send Swaps
|
||||
///
|
||||
/// This covers the case when the swap state is still Created and the swap fails to reach the
|
||||
/// Pending state in time. The TimedOut state indicates the lockup tx should never be broadcast.
|
||||
TimedOut = 4,
|
||||
}
|
||||
impl ToSql for PaymentState {
|
||||
fn to_sql(&self) -> rusqlite::Result<ToSqlOutput<'_>> {
|
||||
@@ -392,6 +398,7 @@ impl FromSql for PaymentState {
|
||||
1 => Ok(PaymentState::Pending),
|
||||
2 => Ok(PaymentState::Complete),
|
||||
3 => Ok(PaymentState::Failed),
|
||||
4 => Ok(PaymentState::TimedOut),
|
||||
_ => Err(FromSqlError::OutOfRange(i)),
|
||||
},
|
||||
_ => Err(FromSqlError::InvalidType),
|
||||
|
||||
@@ -46,6 +46,29 @@ impl Persister {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn update_send_swaps_by_state(
|
||||
&self,
|
||||
from_state: PaymentState,
|
||||
to_state: PaymentState,
|
||||
) -> Result<()> {
|
||||
let con = self.get_connection()?;
|
||||
con.execute(
|
||||
"UPDATE send_swaps
|
||||
SET
|
||||
state = :to_state
|
||||
WHERE
|
||||
state = :from_state
|
||||
",
|
||||
named_params! {
|
||||
":from_state": from_state,
|
||||
":to_state": to_state,
|
||||
},
|
||||
)
|
||||
.map_err(|_| PaymentError::PersistError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_send_swaps_query(where_clauses: Vec<String>) -> String {
|
||||
let mut where_clause_str = String::new();
|
||||
if !where_clauses.is_empty() {
|
||||
|
||||
@@ -133,6 +133,9 @@ impl LiquidSdk {
|
||||
async fn start(self: &Arc<LiquidSdk>) -> LiquidSdkResult<()> {
|
||||
let mut is_started = self.is_started.write().await;
|
||||
let start_ts = Instant::now();
|
||||
|
||||
self.persister
|
||||
.update_send_swaps_by_state(Created, TimedOut)?;
|
||||
self.start_background_tasks().await?;
|
||||
*is_started = true;
|
||||
|
||||
@@ -265,15 +268,20 @@ impl LiquidSdk {
|
||||
}),
|
||||
|
||||
(Created | Pending, Pending) => Ok(()),
|
||||
(Complete | Failed, Pending) => Err(PaymentError::Generic {
|
||||
(Complete | Failed | TimedOut, Pending) => Err(PaymentError::Generic {
|
||||
err: format!("Cannot transition from {from_state:?} to Pending state"),
|
||||
}),
|
||||
|
||||
(Created | Pending, Complete) => Ok(()),
|
||||
(Complete | Failed, Complete) => Err(PaymentError::Generic {
|
||||
(Complete | Failed | TimedOut, Complete) => Err(PaymentError::Generic {
|
||||
err: format!("Cannot transition from {from_state:?} to Complete state"),
|
||||
}),
|
||||
|
||||
(Created, TimedOut) => Ok(()),
|
||||
(_, TimedOut) => Err(PaymentError::Generic {
|
||||
err: format!("Cannot transition from {from_state:?} to TimedOut state"),
|
||||
}),
|
||||
|
||||
(_, Failed) => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -646,6 +654,7 @@ impl LiquidSdk {
|
||||
None => pending_send_sat += p.amount_sat,
|
||||
},
|
||||
Created => pending_send_sat += p.amount_sat,
|
||||
TimedOut => {}
|
||||
},
|
||||
PaymentType::Receive => match p.status {
|
||||
Complete => confirmed_received_sat += p.amount_sat,
|
||||
@@ -1058,7 +1067,11 @@ impl LiquidSdk {
|
||||
tokio::select! {
|
||||
_ = &mut timeout_fut => match maybe_payment {
|
||||
Some(payment) => return Ok(payment),
|
||||
None => return Err(PaymentError::PaymentTimeout),
|
||||
None => {
|
||||
debug!("Timeout occured without payment, set swap to timed out");
|
||||
self.try_handle_send_swap_update(&swap_id, TimedOut, None, None, None).await?;
|
||||
return Err(PaymentError::PaymentTimeout)
|
||||
},
|
||||
},
|
||||
event = events_stream.recv() => match event {
|
||||
Ok(LiquidSdkEvent::PaymentPending { details }) => match details.swap_id.clone() {
|
||||
|
||||
@@ -331,6 +331,12 @@ enum PaymentState {
|
||||
///
|
||||
/// This is the status when a swap refund was initiated and the refund tx is confirmed.
|
||||
failed,
|
||||
|
||||
/// ## Send Swaps
|
||||
///
|
||||
/// This covers the case when the swap state is still Created and the swap fails to reach the
|
||||
/// Pending state in time. The TimedOut state indicates the lockup tx should never be broadcast.
|
||||
timedOut,
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -907,6 +907,9 @@ enum BreezLiquidSDKMapper {
|
||||
case "failed":
|
||||
return PaymentState.failed
|
||||
|
||||
case "timedOut":
|
||||
return PaymentState.timedOut
|
||||
|
||||
default: throw LiquidSdkError.Generic(message: "Invalid variant \(paymentState) for enum PaymentState")
|
||||
}
|
||||
}
|
||||
@@ -924,6 +927,9 @@ enum BreezLiquidSDKMapper {
|
||||
|
||||
case .failed:
|
||||
return "failed"
|
||||
|
||||
case .timedOut:
|
||||
return "timedOut"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,8 @@ export enum PaymentState {
|
||||
CREATED = "created",
|
||||
PENDING = "pending",
|
||||
COMPLETE = "complete",
|
||||
FAILED = "failed"
|
||||
FAILED = "failed",
|
||||
TIMED_OUT = "timedOut"
|
||||
}
|
||||
|
||||
export enum PaymentType {
|
||||
|
||||
Reference in New Issue
Block a user