mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2026-02-11 01:04:25 +01:00
Return pending payment (#245)
* Return pending payment * Simplify select loop * Revert dart pubspec * Add error logging for payment events without swap ids Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com> --------- Co-authored-by: ok300 <106775972+ok300@users.noreply.github.com>
This commit is contained in:
@@ -16,6 +16,7 @@ enum PaymentError {
|
||||
"InvalidPreimage",
|
||||
"LwkError",
|
||||
"PairsNotFound",
|
||||
"PaymentTimeout",
|
||||
"PersistError",
|
||||
"Refunded",
|
||||
"SendError",
|
||||
|
||||
@@ -59,6 +59,9 @@ pub enum PaymentError {
|
||||
#[error("Boltz did not return any pairs from the request")]
|
||||
PairsNotFound,
|
||||
|
||||
#[error("The payment timed out")]
|
||||
PaymentTimeout,
|
||||
|
||||
#[error("Could not store the swap details locally")]
|
||||
PersistError,
|
||||
|
||||
|
||||
@@ -326,21 +326,22 @@ impl CstDecode<crate::error::PaymentError> for wire_cst_payment_error {
|
||||
}
|
||||
}
|
||||
8 => crate::error::PaymentError::PairsNotFound,
|
||||
9 => crate::error::PaymentError::PersistError,
|
||||
10 => {
|
||||
9 => crate::error::PaymentError::PaymentTimeout,
|
||||
10 => crate::error::PaymentError::PersistError,
|
||||
11 => {
|
||||
let ans = unsafe { self.kind.Refunded };
|
||||
crate::error::PaymentError::Refunded {
|
||||
err: ans.err.cst_decode(),
|
||||
refund_tx_id: ans.refund_tx_id.cst_decode(),
|
||||
}
|
||||
}
|
||||
11 => {
|
||||
12 => {
|
||||
let ans = unsafe { self.kind.SendError };
|
||||
crate::error::PaymentError::SendError {
|
||||
err: ans.err.cst_decode(),
|
||||
}
|
||||
}
|
||||
12 => {
|
||||
13 => {
|
||||
let ans = unsafe { self.kind.SignerError };
|
||||
crate::error::PaymentError::SignerError {
|
||||
err: ans.err.cst_decode(),
|
||||
|
||||
@@ -821,9 +821,12 @@ impl SseDecode for crate::error::PaymentError {
|
||||
return crate::error::PaymentError::PairsNotFound;
|
||||
}
|
||||
9 => {
|
||||
return crate::error::PaymentError::PersistError;
|
||||
return crate::error::PaymentError::PaymentTimeout;
|
||||
}
|
||||
10 => {
|
||||
return crate::error::PaymentError::PersistError;
|
||||
}
|
||||
11 => {
|
||||
let mut var_err = <String>::sse_decode(deserializer);
|
||||
let mut var_refundTxId = <String>::sse_decode(deserializer);
|
||||
return crate::error::PaymentError::Refunded {
|
||||
@@ -831,11 +834,11 @@ impl SseDecode for crate::error::PaymentError {
|
||||
refund_tx_id: var_refundTxId,
|
||||
};
|
||||
}
|
||||
11 => {
|
||||
12 => {
|
||||
let mut var_err = <String>::sse_decode(deserializer);
|
||||
return crate::error::PaymentError::SendError { err: var_err };
|
||||
}
|
||||
12 => {
|
||||
13 => {
|
||||
let mut var_err = <String>::sse_decode(deserializer);
|
||||
return crate::error::PaymentError::SignerError { err: var_err };
|
||||
}
|
||||
@@ -1258,18 +1261,19 @@ impl flutter_rust_bridge::IntoDart for crate::error::PaymentError {
|
||||
[7.into_dart(), err.into_into_dart().into_dart()].into_dart()
|
||||
}
|
||||
crate::error::PaymentError::PairsNotFound => [8.into_dart()].into_dart(),
|
||||
crate::error::PaymentError::PersistError => [9.into_dart()].into_dart(),
|
||||
crate::error::PaymentError::PaymentTimeout => [9.into_dart()].into_dart(),
|
||||
crate::error::PaymentError::PersistError => [10.into_dart()].into_dart(),
|
||||
crate::error::PaymentError::Refunded { err, refund_tx_id } => [
|
||||
10.into_dart(),
|
||||
11.into_dart(),
|
||||
err.into_into_dart().into_dart(),
|
||||
refund_tx_id.into_into_dart().into_dart(),
|
||||
]
|
||||
.into_dart(),
|
||||
crate::error::PaymentError::SendError { err } => {
|
||||
[11.into_dart(), err.into_into_dart().into_dart()].into_dart()
|
||||
[12.into_dart(), err.into_into_dart().into_dart()].into_dart()
|
||||
}
|
||||
crate::error::PaymentError::SignerError { err } => {
|
||||
[12.into_dart(), err.into_into_dart().into_dart()].into_dart()
|
||||
[13.into_dart(), err.into_into_dart().into_dart()].into_dart()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1753,20 +1757,23 @@ impl SseEncode for crate::error::PaymentError {
|
||||
crate::error::PaymentError::PairsNotFound => {
|
||||
<i32>::sse_encode(8, serializer);
|
||||
}
|
||||
crate::error::PaymentError::PersistError => {
|
||||
crate::error::PaymentError::PaymentTimeout => {
|
||||
<i32>::sse_encode(9, serializer);
|
||||
}
|
||||
crate::error::PaymentError::Refunded { err, refund_tx_id } => {
|
||||
crate::error::PaymentError::PersistError => {
|
||||
<i32>::sse_encode(10, serializer);
|
||||
}
|
||||
crate::error::PaymentError::Refunded { err, refund_tx_id } => {
|
||||
<i32>::sse_encode(11, serializer);
|
||||
<String>::sse_encode(err, serializer);
|
||||
<String>::sse_encode(refund_tx_id, serializer);
|
||||
}
|
||||
crate::error::PaymentError::SendError { err } => {
|
||||
<i32>::sse_encode(11, serializer);
|
||||
<i32>::sse_encode(12, serializer);
|
||||
<String>::sse_encode(err, serializer);
|
||||
}
|
||||
crate::error::PaymentError::SignerError { err } => {
|
||||
<i32>::sse_encode(12, serializer);
|
||||
<i32>::sse_encode(13, serializer);
|
||||
<String>::sse_encode(err, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,6 +1019,7 @@ impl LiquidSdk {
|
||||
})?;
|
||||
|
||||
let swap_id = &create_response.id;
|
||||
let accept_zero_conf = create_response.accept_zero_conf;
|
||||
let create_response_json = SendSwap::from_boltz_struct_to_json(&create_response, swap_id)?;
|
||||
|
||||
let payer_amount_sat = req.fees_sat + receiver_amount_sat;
|
||||
@@ -1035,28 +1036,55 @@ impl LiquidSdk {
|
||||
refund_private_key: keypair.display_secret().to_string(),
|
||||
};
|
||||
self.persister.insert_send_swap(&swap)?;
|
||||
|
||||
let mut events_stream = self.event_manager.subscribe();
|
||||
self.status_stream.track_swap_id(swap_id)?;
|
||||
|
||||
self.wait_for_payment(swap.id, accept_zero_conf)
|
||||
.await
|
||||
.map(|payment| SendPaymentResponse { payment })
|
||||
}
|
||||
|
||||
async fn wait_for_payment(
|
||||
&self,
|
||||
swap_id: String,
|
||||
accept_zero_conf: bool,
|
||||
) -> Result<Payment, PaymentError> {
|
||||
let timeout_fut = tokio::time::sleep(Duration::from_secs(15));
|
||||
tokio::pin!(timeout_fut);
|
||||
|
||||
let mut events_stream = self.event_manager.subscribe();
|
||||
let mut maybe_payment: Option<Payment> = None;
|
||||
|
||||
loop {
|
||||
match events_stream.recv().await {
|
||||
Ok(LiquidSdkEvent::PaymentFailed { details }) => match details.swap_id {
|
||||
Some(id) if id == swap.id => {
|
||||
return Err(PaymentError::SendError {
|
||||
err: "Payment failed".to_string(),
|
||||
})
|
||||
}
|
||||
_ => (),
|
||||
tokio::select! {
|
||||
_ = &mut timeout_fut => match maybe_payment {
|
||||
Some(payment) => return Ok(payment),
|
||||
None => return Err(PaymentError::PaymentTimeout),
|
||||
},
|
||||
Ok(LiquidSdkEvent::PaymentSucceed { details }) => match details.swap_id.clone() {
|
||||
Some(id) if id == swap.id => {
|
||||
return Ok(SendPaymentResponse { payment: details })
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Ok(event) => debug!("Unhandled event: {event:?}"),
|
||||
Err(e) => debug!("Received error waiting for event: {e:?}"),
|
||||
event = events_stream.recv() => match event {
|
||||
Ok(LiquidSdkEvent::PaymentPending { details }) => match details.swap_id.clone() {
|
||||
Some(id) if id == swap_id => match accept_zero_conf {
|
||||
true => {
|
||||
debug!("Received Send Payment pending event with zero-conf accepted");
|
||||
return Ok(details)
|
||||
}
|
||||
false => {
|
||||
debug!("Received Send Payment pending event, waiting for confirmation");
|
||||
maybe_payment = Some(details);
|
||||
}
|
||||
},
|
||||
_ => error!("Received Send Payment pending event for payment without swap ID"),
|
||||
},
|
||||
Ok(LiquidSdkEvent::PaymentSucceed { details }) => match details.swap_id.clone()
|
||||
{
|
||||
Some(id) if id == swap_id => {
|
||||
debug!("Received Send Payment succeed event");
|
||||
return Ok(details);
|
||||
}
|
||||
_ => error!("Received Send Payment succeed event for payment without swap ID"),
|
||||
},
|
||||
Ok(event) => debug!("Unhandled event: {event:?}"),
|
||||
Err(e) => debug!("Received error waiting for event: {e:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ sealed class PaymentError with _$PaymentError implements FrbException {
|
||||
required String err,
|
||||
}) = PaymentError_LwkError;
|
||||
const factory PaymentError.pairsNotFound() = PaymentError_PairsNotFound;
|
||||
const factory PaymentError.paymentTimeout() = PaymentError_PaymentTimeout;
|
||||
const factory PaymentError.persistError() = PaymentError_PersistError;
|
||||
const factory PaymentError.refunded({
|
||||
required String err,
|
||||
|
||||
@@ -638,6 +638,47 @@ abstract class PaymentError_PairsNotFound extends PaymentError {
|
||||
const PaymentError_PairsNotFound._() : super._();
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PaymentError_PaymentTimeoutImplCopyWith<$Res> {
|
||||
factory _$$PaymentError_PaymentTimeoutImplCopyWith(
|
||||
_$PaymentError_PaymentTimeoutImpl value, $Res Function(_$PaymentError_PaymentTimeoutImpl) then) =
|
||||
__$$PaymentError_PaymentTimeoutImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PaymentError_PaymentTimeoutImplCopyWithImpl<$Res>
|
||||
extends _$PaymentErrorCopyWithImpl<$Res, _$PaymentError_PaymentTimeoutImpl>
|
||||
implements _$$PaymentError_PaymentTimeoutImplCopyWith<$Res> {
|
||||
__$$PaymentError_PaymentTimeoutImplCopyWithImpl(
|
||||
_$PaymentError_PaymentTimeoutImpl _value, $Res Function(_$PaymentError_PaymentTimeoutImpl) _then)
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$PaymentError_PaymentTimeoutImpl extends PaymentError_PaymentTimeout {
|
||||
const _$PaymentError_PaymentTimeoutImpl() : super._();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PaymentError.paymentTimeout()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$PaymentError_PaymentTimeoutImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
}
|
||||
|
||||
abstract class PaymentError_PaymentTimeout extends PaymentError {
|
||||
const factory PaymentError_PaymentTimeout() = _$PaymentError_PaymentTimeoutImpl;
|
||||
const PaymentError_PaymentTimeout._() : super._();
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PaymentError_PersistErrorImplCopyWith<$Res> {
|
||||
factory _$$PaymentError_PersistErrorImplCopyWith(
|
||||
|
||||
@@ -800,17 +800,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
case 8:
|
||||
return PaymentError_PairsNotFound();
|
||||
case 9:
|
||||
return PaymentError_PersistError();
|
||||
return PaymentError_PaymentTimeout();
|
||||
case 10:
|
||||
return PaymentError_PersistError();
|
||||
case 11:
|
||||
return PaymentError_Refunded(
|
||||
err: dco_decode_String(raw[1]),
|
||||
refundTxId: dco_decode_String(raw[2]),
|
||||
);
|
||||
case 11:
|
||||
case 12:
|
||||
return PaymentError_SendError(
|
||||
err: dco_decode_String(raw[1]),
|
||||
);
|
||||
case 12:
|
||||
case 13:
|
||||
return PaymentError_SignerError(
|
||||
err: dco_decode_String(raw[1]),
|
||||
);
|
||||
@@ -1309,15 +1311,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
case 8:
|
||||
return PaymentError_PairsNotFound();
|
||||
case 9:
|
||||
return PaymentError_PersistError();
|
||||
return PaymentError_PaymentTimeout();
|
||||
case 10:
|
||||
return PaymentError_PersistError();
|
||||
case 11:
|
||||
var var_err = sse_decode_String(deserializer);
|
||||
var var_refundTxId = sse_decode_String(deserializer);
|
||||
return PaymentError_Refunded(err: var_err, refundTxId: var_refundTxId);
|
||||
case 11:
|
||||
case 12:
|
||||
var var_err = sse_decode_String(deserializer);
|
||||
return PaymentError_SendError(err: var_err);
|
||||
case 12:
|
||||
case 13:
|
||||
var var_err = sse_decode_String(deserializer);
|
||||
return PaymentError_SignerError(err: var_err);
|
||||
default:
|
||||
@@ -1815,17 +1819,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
sse_encode_String(err, serializer);
|
||||
case PaymentError_PairsNotFound():
|
||||
sse_encode_i_32(8, serializer);
|
||||
case PaymentError_PersistError():
|
||||
case PaymentError_PaymentTimeout():
|
||||
sse_encode_i_32(9, serializer);
|
||||
case PaymentError_Refunded(err: final err, refundTxId: final refundTxId):
|
||||
case PaymentError_PersistError():
|
||||
sse_encode_i_32(10, serializer);
|
||||
case PaymentError_Refunded(err: final err, refundTxId: final refundTxId):
|
||||
sse_encode_i_32(11, serializer);
|
||||
sse_encode_String(err, serializer);
|
||||
sse_encode_String(refundTxId, serializer);
|
||||
case PaymentError_SendError(err: final err):
|
||||
sse_encode_i_32(11, serializer);
|
||||
sse_encode_i_32(12, serializer);
|
||||
sse_encode_String(err, serializer);
|
||||
case PaymentError_SignerError(err: final err):
|
||||
sse_encode_i_32(12, serializer);
|
||||
sse_encode_i_32(13, serializer);
|
||||
sse_encode_String(err, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,27 +697,31 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
wireObj.tag = 8;
|
||||
return;
|
||||
}
|
||||
if (apiObj is PaymentError_PersistError) {
|
||||
if (apiObj is PaymentError_PaymentTimeout) {
|
||||
wireObj.tag = 9;
|
||||
return;
|
||||
}
|
||||
if (apiObj is PaymentError_PersistError) {
|
||||
wireObj.tag = 10;
|
||||
return;
|
||||
}
|
||||
if (apiObj is PaymentError_Refunded) {
|
||||
var pre_err = cst_encode_String(apiObj.err);
|
||||
var pre_refund_tx_id = cst_encode_String(apiObj.refundTxId);
|
||||
wireObj.tag = 10;
|
||||
wireObj.tag = 11;
|
||||
wireObj.kind.Refunded.err = pre_err;
|
||||
wireObj.kind.Refunded.refund_tx_id = pre_refund_tx_id;
|
||||
return;
|
||||
}
|
||||
if (apiObj is PaymentError_SendError) {
|
||||
var pre_err = cst_encode_String(apiObj.err);
|
||||
wireObj.tag = 11;
|
||||
wireObj.tag = 12;
|
||||
wireObj.kind.SendError.err = pre_err;
|
||||
return;
|
||||
}
|
||||
if (apiObj is PaymentError_SignerError) {
|
||||
var pre_err = cst_encode_String(apiObj.err);
|
||||
wireObj.tag = 12;
|
||||
wireObj.tag = 13;
|
||||
wireObj.kind.SignerError.err = pre_err;
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user