Send: store preimage on Complete

This commit is contained in:
ok300
2024-05-23 08:11:07 +02:00
parent fcee44b1c2
commit 9d5097a55c
16 changed files with 91 additions and 21 deletions

View File

@@ -63,6 +63,7 @@ typedef struct wire_cst_payment {
uint32_t timestamp;
uint64_t amount_sat;
uint64_t *fees_sat;
struct wire_cst_list_prim_u_8_strict *preimage;
int32_t payment_type;
int32_t status;
} wire_cst_payment;

View File

@@ -79,6 +79,7 @@ dictionary Payment {
u32 timestamp;
u64 amount_sat;
u64? fees_sat = null;
string? preimage = null;
PaymentType payment_type;
PaymentState status;
};

View File

@@ -172,6 +172,7 @@ impl CstDecode<crate::model::Payment> for wire_cst_payment {
timestamp: self.timestamp.cst_decode(),
amount_sat: self.amount_sat.cst_decode(),
fees_sat: self.fees_sat.cst_decode(),
preimage: self.preimage.cst_decode(),
payment_type: self.payment_type.cst_decode(),
status: self.status.cst_decode(),
}
@@ -345,6 +346,7 @@ impl NewWithNullPtr for wire_cst_payment {
timestamp: Default::default(),
amount_sat: Default::default(),
fees_sat: core::ptr::null_mut(),
preimage: core::ptr::null_mut(),
payment_type: Default::default(),
status: Default::default(),
}
@@ -693,6 +695,7 @@ pub struct wire_cst_payment {
timestamp: u32,
amount_sat: u64,
fees_sat: *mut u64,
preimage: *mut wire_cst_list_prim_u_8_strict,
payment_type: i32,
status: i32,
}

View File

@@ -592,6 +592,7 @@ impl SseDecode for crate::model::Payment {
let mut var_timestamp = <u32>::sse_decode(deserializer);
let mut var_amountSat = <u64>::sse_decode(deserializer);
let mut var_feesSat = <Option<u64>>::sse_decode(deserializer);
let mut var_preimage = <Option<String>>::sse_decode(deserializer);
let mut var_paymentType = <crate::model::PaymentType>::sse_decode(deserializer);
let mut var_status = <crate::model::PaymentState>::sse_decode(deserializer);
return crate::model::Payment {
@@ -600,6 +601,7 @@ impl SseDecode for crate::model::Payment {
timestamp: var_timestamp,
amount_sat: var_amountSat,
fees_sat: var_feesSat,
preimage: var_preimage,
payment_type: var_paymentType,
status: var_status,
};
@@ -936,6 +938,7 @@ impl flutter_rust_bridge::IntoDart for crate::model::Payment {
self.timestamp.into_into_dart().into_dart(),
self.amount_sat.into_into_dart().into_dart(),
self.fees_sat.into_into_dart().into_dart(),
self.preimage.into_into_dart().into_dart(),
self.payment_type.into_into_dart().into_dart(),
self.status.into_into_dart().into_dart(),
]
@@ -1289,6 +1292,7 @@ impl SseEncode for crate::model::Payment {
<u32>::sse_encode(self.timestamp, serializer);
<u64>::sse_encode(self.amount_sat, serializer);
<Option<u64>>::sse_encode(self.fees_sat, serializer);
<Option<String>>::sse_encode(self.preimage, serializer);
<crate::model::PaymentType>::sse_encode(self.payment_type, serializer);
<crate::model::PaymentState>::sse_encode(self.status, serializer);
}

View File

@@ -425,6 +425,8 @@ pub struct PaymentSwapData {
/// Swap creation timestamp
pub created_at: u32,
pub preimage: Option<String>,
/// Amount sent by the swap payer
pub payer_amount_sat: u64,
@@ -463,6 +465,9 @@ pub struct Payment {
/// received.
pub fees_sat: Option<u64>,
/// In case of a Send swap, this is the preimage of the paid invoice (proof of payment).
pub preimage: Option<String>,
pub payment_type: PaymentType,
/// Composite status representing the overall status of the payment.
@@ -485,6 +490,7 @@ impl Payment {
fees_sat: swap
.as_ref()
.map(|s| s.payer_amount_sat - s.receiver_amount_sat),
preimage: swap.as_ref().and_then(|s| s.preimage.clone()),
payment_type: tx.payment_type,
status: match swap {
Some(swap) => swap.status,

View File

@@ -15,6 +15,7 @@ pub(crate) fn current_migrations() -> Vec<&'static str> {
"CREATE TABLE IF NOT EXISTS send_swaps (
id TEXT NOT NULL PRIMARY KEY,
invoice TEXT NOT NULL,
preimage TEXT,
payer_amount_sat INTEGER NOT NULL,
receiver_amount_sat INTEGER NOT NULL,
create_response_json TEXT NOT NULL,

View File

@@ -112,6 +112,7 @@ impl Persister {
rs.state,
ss.id,
ss.created_at,
ss.preimage,
ss.payer_amount_sat,
ss.receiver_amount_sat,
ss.state
@@ -140,14 +141,16 @@ impl Persister {
let maybe_receive_swap_receiver_state: Option<PaymentState> = row.get(9)?;
let maybe_send_swap_id: Option<String> = row.get(10)?;
let maybe_send_swap_created_at: Option<u32> = row.get(11)?;
let maybe_send_swap_payer_amount_sat: Option<u64> = row.get(12)?;
let maybe_send_swap_receiver_amount_sat: Option<u64> = row.get(13)?;
let maybe_send_swap_state: Option<PaymentState> = row.get(14)?;
let maybe_send_swap_preimage: Option<String> = row.get(12)?;
let maybe_send_swap_payer_amount_sat: Option<u64> = row.get(13)?;
let maybe_send_swap_receiver_amount_sat: Option<u64> = row.get(14)?;
let maybe_send_swap_state: Option<PaymentState> = row.get(15)?;
let swap = match maybe_receive_swap_id {
Some(receive_swap_id) => Some(PaymentSwapData {
swap_id: receive_swap_id,
created_at: maybe_receive_swap_created_at.unwrap_or(utils::now()),
preimage: None,
payer_amount_sat: maybe_receive_swap_payer_amount_sat.unwrap_or(0),
receiver_amount_sat: maybe_receive_swap_receiver_amount_sat.unwrap_or(0),
status: maybe_receive_swap_receiver_state.unwrap_or(PaymentState::Created),
@@ -155,6 +158,7 @@ impl Persister {
None => maybe_send_swap_id.map(|send_swap_id| PaymentSwapData {
swap_id: send_swap_id,
created_at: maybe_send_swap_created_at.unwrap_or(utils::now()),
preimage: maybe_send_swap_preimage,
payer_amount_sat: maybe_send_swap_payer_amount_sat.unwrap_or(0),
receiver_amount_sat: maybe_send_swap_receiver_amount_sat.unwrap_or(0),
status: maybe_send_swap_state.unwrap_or(PaymentState::Created),

View File

@@ -160,13 +160,20 @@ impl Persister {
con: &Connection,
swap_id: &str,
to_state: PaymentState,
preimage: Option<&str>,
lockup_tx_id: Option<&str>,
refund_tx_id: Option<&str>,
) -> Result<(), PaymentError> {
// Do not overwrite lockup_tx_id, refund_tx_id
// Do not overwrite preimage, lockup_tx_id, refund_tx_id
con.execute(
"UPDATE send_swaps
SET
preimage =
CASE
WHEN preimage IS NULL THEN :preimage
ELSE preimage
END,
lockup_tx_id =
CASE
WHEN lockup_tx_id IS NULL THEN :lockup_tx_id
@@ -179,11 +186,12 @@ impl Persister {
ELSE refund_tx_id
END,
state=:state
state = :state
WHERE
id = :id",
named_params! {
":id": swap_id,
":preimage": preimage,
":lockup_tx_id": lockup_tx_id,
":refund_tx_id": refund_tx_id,
":state": to_state,

View File

@@ -192,6 +192,7 @@ impl LiquidSdk {
&self,
swap_id: &str,
to_state: PaymentState,
preimage: Option<&str>,
lockup_tx_id: Option<&str>,
refund_tx_id: Option<&str>,
) -> Result<(), PaymentError> {
@@ -209,6 +210,7 @@ impl LiquidSdk {
&con,
swap_id,
to_state,
preimage,
lockup_tx_id,
refund_tx_id,
)
@@ -339,7 +341,7 @@ impl LiquidSdk {
let refund_tx_id =
self.try_refund(id, &swap_script, &keypair, receiver_amount_sat)?;
info!("Broadcast refund tx for Swap-in {id}. Tx id: {refund_tx_id}");
self.try_handle_send_swap_update(id, Pending, None, Some(&refund_tx_id))?;
self.try_handle_send_swap_update(id, Pending, None, None, Some(&refund_tx_id))?;
Ok(())
}
@@ -587,7 +589,13 @@ impl LiquidSdk {
Self::verify_payment_hash(&claim_tx_response.preimage, invoice)?;
// After we confirm the preimage is correct, we mark this as complete
self.try_handle_send_swap_update(swap_id, Complete, None, None)?;
self.try_handle_send_swap_update(
swap_id,
Complete,
Some(&claim_tx_response.preimage),
None,
None,
)?;
let (partial_sig, pub_nonce) =
refund_tx.submarine_partial_sig(keypair, &claim_tx_response)?;
@@ -720,7 +728,13 @@ impl LiquidSdk {
};
lockup_tx_id = self.lockup_funds(swap_id, &create_response)?;
self.try_handle_send_swap_update(swap_id, Pending, Some(&lockup_tx_id), None)?;
self.try_handle_send_swap_update(
swap_id,
Pending,
None,
Some(&lockup_tx_id),
None,
)?;
}
// Boltz has detected the lockup in the mempool, we can speed up
@@ -962,7 +976,7 @@ impl LiquidSdk {
self.try_handle_receive_swap_update(&swap.id, Complete, None)?;
}
if let Some(swap) = pending_send_swaps_by_refund_tx_id.get(&tx_id) {
self.try_handle_send_swap_update(&swap.id, Failed, None, None)?;
self.try_handle_send_swap_update(&swap.id, Failed, None, None, None)?;
}
}

View File

@@ -517,15 +517,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
Payment dco_decode_payment(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
final arr = raw as List<dynamic>;
if (arr.length != 7) throw Exception('unexpected arr length: expect 7 but see ${arr.length}');
if (arr.length != 8) throw Exception('unexpected arr length: expect 8 but see ${arr.length}');
return Payment(
txId: dco_decode_String(arr[0]),
swapId: dco_decode_opt_String(arr[1]),
timestamp: dco_decode_u_32(arr[2]),
amountSat: dco_decode_u_64(arr[3]),
feesSat: dco_decode_opt_box_autoadd_u_64(arr[4]),
paymentType: dco_decode_payment_type(arr[5]),
status: dco_decode_payment_state(arr[6]),
preimage: dco_decode_opt_String(arr[5]),
paymentType: dco_decode_payment_type(arr[6]),
status: dco_decode_payment_state(arr[7]),
);
}
@@ -880,6 +881,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
var var_timestamp = sse_decode_u_32(deserializer);
var var_amountSat = sse_decode_u_64(deserializer);
var var_feesSat = sse_decode_opt_box_autoadd_u_64(deserializer);
var var_preimage = sse_decode_opt_String(deserializer);
var var_paymentType = sse_decode_payment_type(deserializer);
var var_status = sse_decode_payment_state(deserializer);
return Payment(
@@ -888,6 +890,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
timestamp: var_timestamp,
amountSat: var_amountSat,
feesSat: var_feesSat,
preimage: var_preimage,
paymentType: var_paymentType,
status: var_status);
}
@@ -1279,6 +1282,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
sse_encode_u_32(self.timestamp, serializer);
sse_encode_u_64(self.amountSat, serializer);
sse_encode_opt_box_autoadd_u_64(self.feesSat, serializer);
sse_encode_opt_String(self.preimage, serializer);
sse_encode_payment_type(self.paymentType, serializer);
sse_encode_payment_state(self.status, serializer);
}

View File

@@ -454,6 +454,7 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
wireObj.timestamp = cst_encode_u_32(apiObj.timestamp);
wireObj.amount_sat = cst_encode_u_64(apiObj.amountSat);
wireObj.fees_sat = cst_encode_opt_box_autoadd_u_64(apiObj.feesSat);
wireObj.preimage = cst_encode_opt_String(apiObj.preimage);
wireObj.payment_type = cst_encode_payment_type(apiObj.paymentType);
wireObj.status = cst_encode_payment_state(apiObj.status);
}
@@ -1156,6 +1157,8 @@ final class wire_cst_payment extends ffi.Struct {
external ffi.Pointer<ffi.Uint64> fees_sat;
external ffi.Pointer<wire_cst_list_prim_u_8_strict> preimage;
@ffi.Int32()
external int payment_type;

View File

@@ -111,6 +111,9 @@ class Payment {
/// sender. In other words, it's the delta between the amount that was sent and the amount
/// received.
final int? feesSat;
/// In case of a Send swap, this is the preimage of the paid invoice (proof of payment).
final String? preimage;
final PaymentType paymentType;
/// Composite status representing the overall status of the payment.
@@ -126,6 +129,7 @@ class Payment {
required this.timestamp,
required this.amountSat,
this.feesSat,
this.preimage,
required this.paymentType,
required this.status,
});
@@ -137,6 +141,7 @@ class Payment {
timestamp.hashCode ^
amountSat.hashCode ^
feesSat.hashCode ^
preimage.hashCode ^
paymentType.hashCode ^
status.hashCode;
@@ -150,6 +155,7 @@ class Payment {
timestamp == other.timestamp &&
amountSat == other.amountSat &&
feesSat == other.feesSat &&
preimage == other.preimage &&
paymentType == other.paymentType &&
status == other.status;
}

View File

@@ -454,6 +454,8 @@ final class wire_cst_payment extends ffi.Struct {
external ffi.Pointer<ffi.Uint64> fees_sat;
external ffi.Pointer<wire_cst_list_prim_u_8_strict> preimage;
@ffi.Int32()
external int payment_type;

View File

@@ -140,6 +140,7 @@ fun asPayment(payment: ReadableMap): Payment? {
val timestamp = payment.getInt("timestamp").toUInt()
val amountSat = payment.getDouble("amountSat").toULong()
val feesSat = if (hasNonNullKey(payment, "feesSat")) payment.getDouble("feesSat").toULong() else null
val preimage = if (hasNonNullKey(payment, "preimage")) payment.getString("preimage") else null
val paymentType = payment.getString("paymentType")?.let { asPaymentType(it) }!!
val status = payment.getString("status")?.let { asPaymentState(it) }!!
return Payment(
@@ -148,6 +149,7 @@ fun asPayment(payment: ReadableMap): Payment? {
timestamp,
amountSat,
feesSat,
preimage,
paymentType,
status,
)
@@ -160,6 +162,7 @@ fun readableMapOf(payment: Payment): ReadableMap {
"timestamp" to payment.timestamp,
"amountSat" to payment.amountSat,
"feesSat" to payment.feesSat,
"preimage" to payment.preimage,
"paymentType" to payment.paymentType.name.lowercase(),
"status" to payment.status.name.lowercase(),
)

View File

@@ -155,6 +155,13 @@ enum BreezLiquidSDKMapper {
}
feesSat = feesSatTmp
}
var preimage: String?
if hasNonNilKey(data: payment, key: "preimage") {
guard let preimageTmp = payment["preimage"] as? String else {
throw LiquidSdkError.Generic(message: errUnexpectedValue(fieldName: "preimage"))
}
preimage = preimageTmp
}
guard let paymentTypeTmp = payment["paymentType"] as? String else {
throw LiquidSdkError.Generic(message: errMissingMandatoryField(fieldName: "paymentType", typeName: "Payment"))
}
@@ -171,6 +178,7 @@ enum BreezLiquidSDKMapper {
timestamp: timestamp,
amountSat: amountSat,
feesSat: feesSat,
preimage: preimage,
paymentType: paymentType,
status: status
)
@@ -183,6 +191,7 @@ enum BreezLiquidSDKMapper {
"timestamp": payment.timestamp,
"amountSat": payment.amountSat,
"feesSat": payment.feesSat == nil ? nil : payment.feesSat,
"preimage": payment.preimage == nil ? nil : payment.preimage,
"paymentType": valueOf(paymentType: payment.paymentType),
"status": valueOf(paymentState: payment.status),
]

View File

@@ -40,6 +40,7 @@ export interface Payment {
timestamp: number
amountSat: number
feesSat?: number
preimage?: string
paymentType: PaymentType
status: PaymentState
}