Skip to content

Commit

Permalink
Merge pull request #679 from breez/savage-keysend-extratlvs
Browse files Browse the repository at this point in the history
Add extra TLVs to send spontaneous payment
  • Loading branch information
dangeross authored Dec 12, 2023
2 parents 5c8d56e + 023629c commit 57e6d2d
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 6 deletions.
6 changes: 6 additions & 0 deletions libs/sdk-bindings/src/breez_sdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ interface PaymentDetails {
ClosedChannel(ClosedChannelPaymentDetails data);
};

dictionary TlvEntry {
u64 field_number;
sequence<u8> value;
};

[Enum]
interface AesSuccessActionDataResult {
Decrypted(AesSuccessActionDataDecrypted data);
Expand Down Expand Up @@ -678,6 +683,7 @@ dictionary SendPaymentRequest {
dictionary SendSpontaneousPaymentRequest {
string node_id;
u64 amount_msat;
sequence<TlvEntry>? extra_tlvs = null;
};

dictionary SendPaymentResponse {
Expand Down
2 changes: 1 addition & 1 deletion libs/sdk-bindings/src/uniffi_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use breez_sdk_core::{
SendPaymentRequest, SendPaymentResponse, SendSpontaneousPaymentRequest,
ServiceHealthCheckResponse, SignMessageRequest, SignMessageResponse, StaticBackupRequest,
StaticBackupResponse, SuccessActionProcessed, SwapInfo, SwapStatus, SweepRequest,
SweepResponse, Symbol, UnspentTransactionOutput, UrlSuccessActionData,
SweepResponse, Symbol, TlvEntry, UnspentTransactionOutput, UrlSuccessActionData,
};
use log::{Level, LevelFilter, Metadata, Record};
use once_cell::sync::{Lazy, OnceCell};
Expand Down
2 changes: 1 addition & 1 deletion libs/sdk-core/src/breez_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ impl BreezServices {
self.start_node().await?;
let payment_res = self
.node_api
.send_spontaneous_payment(req.node_id.clone(), req.amount_msat)
.send_spontaneous_payment(req.node_id.clone(), req.amount_msat, req.extra_tlvs)
.map_err(Into::into)
.await;
let payment = self
Expand Down
58 changes: 58 additions & 0 deletions libs/sdk-core/src/bridge_generated.io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,15 @@ pub extern "C" fn new_list_payment_type_filter_0(len: i32) -> *mut wire_list_pay
support::new_leak_box_ptr(wrap)
}

#[no_mangle]
pub extern "C" fn new_list_tlv_entry_0(len: i32) -> *mut wire_list_tlv_entry {
let wrap = wire_list_tlv_entry {
ptr: support::new_leak_vec_ptr(<wire_TlvEntry>::new_with_null_ptr(), len),
len,
};
support::new_leak_box_ptr(wrap)
}

#[no_mangle]
pub extern "C" fn new_uint_8_list_0(len: i32) -> *mut wire_uint_8_list {
let ans = wire_uint_8_list {
Expand Down Expand Up @@ -697,6 +706,15 @@ impl Wire2Api<ListPaymentsRequest> for wire_ListPaymentsRequest {
}
}
}
impl Wire2Api<Vec<TlvEntry>> for *mut wire_list_tlv_entry {
fn wire2api(self) -> Vec<TlvEntry> {
let vec = unsafe {
let wrap = support::box_from_leak_ptr(self);
support::vec_from_leak_ptr(wrap.ptr, wrap.len)
};
vec.into_iter().map(Wire2Api::wire2api).collect()
}
}
impl Wire2Api<LnUrlAuthRequestData> for wire_LnUrlAuthRequestData {
fn wire2api(self) -> LnUrlAuthRequestData {
LnUrlAuthRequestData {
Expand Down Expand Up @@ -883,6 +901,7 @@ impl Wire2Api<SendSpontaneousPaymentRequest> for wire_SendSpontaneousPaymentRequ
SendSpontaneousPaymentRequest {
node_id: self.node_id.wire2api(),
amount_msat: self.amount_msat.wire2api(),
extra_tlvs: self.extra_tlvs.wire2api(),
}
}
}
Expand All @@ -908,6 +927,14 @@ impl Wire2Api<SweepRequest> for wire_SweepRequest {
}
}
}
impl Wire2Api<TlvEntry> for wire_TlvEntry {
fn wire2api(self) -> TlvEntry {
TlvEntry {
field_number: self.field_number.wire2api(),
value: self.value.wire2api(),
}
}
}

impl Wire2Api<Vec<u8>> for *mut wire_uint_8_list {
fn wire2api(self) -> Vec<u8> {
Expand Down Expand Up @@ -981,6 +1008,13 @@ pub struct wire_ListPaymentsRequest {
limit: *mut u32,
}

#[repr(C)]
#[derive(Clone)]
pub struct wire_list_tlv_entry {
ptr: *mut wire_TlvEntry,
len: i32,
}

#[repr(C)]
#[derive(Clone)]
pub struct wire_LnUrlAuthRequestData {
Expand Down Expand Up @@ -1121,6 +1155,7 @@ pub struct wire_SendPaymentRequest {
pub struct wire_SendSpontaneousPaymentRequest {
node_id: *mut wire_uint_8_list,
amount_msat: u64,
extra_tlvs: *mut wire_list_tlv_entry,
}

#[repr(C)]
Expand All @@ -1142,6 +1177,13 @@ pub struct wire_SweepRequest {
sat_per_vbyte: u32,
}

#[repr(C)]
#[derive(Clone)]
pub struct wire_TlvEntry {
field_number: u64,
value: *mut wire_uint_8_list,
}

#[repr(C)]
#[derive(Clone)]
pub struct wire_uint_8_list {
Expand Down Expand Up @@ -1616,6 +1658,7 @@ impl NewWithNullPtr for wire_SendSpontaneousPaymentRequest {
Self {
node_id: core::ptr::null_mut(),
amount_msat: Default::default(),
extra_tlvs: core::ptr::null_mut(),
}
}
}
Expand Down Expand Up @@ -1669,6 +1712,21 @@ impl Default for wire_SweepRequest {
}
}

impl NewWithNullPtr for wire_TlvEntry {
fn new_with_null_ptr() -> Self {
Self {
field_number: Default::default(),
value: core::ptr::null_mut(),
}
}
}

impl Default for wire_TlvEntry {
fn default() -> Self {
Self::new_with_null_ptr()
}
}

// Section: sync execution mode utility

#[no_mangle]
Expand Down
1 change: 1 addition & 0 deletions libs/sdk-core/src/bridge_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ use crate::models::SwapInfo;
use crate::models::SwapStatus;
use crate::models::SweepRequest;
use crate::models::SweepResponse;
use crate::models::TlvEntry;
use crate::models::UnspentTransactionOutput;

// Section: wire functions
Expand Down
11 changes: 10 additions & 1 deletion libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,7 @@ impl NodeAPI for Greenlight {
&self,
node_id: String,
amount_msat: u64,
extra_tlvs: Option<Vec<TlvEntry>>,
) -> NodeResult<Payment> {
let mut client: node::ClnClient = self.get_node_client().await?;
let request = cln::KeysendRequest {
Expand All @@ -912,7 +913,15 @@ impl NodeAPI for Greenlight {
"breez-{}",
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
)),
extratlvs: None,
extratlvs: extra_tlvs.map(|tlvs| cln::TlvStream {
entries: tlvs
.into_iter()
.map(|tlv| cln::TlvEntry {
r#type: tlv.field_number,
value: tlv.value,
})
.collect(),
}),
routehints: None,
maxfeepercent: Some(self.sdk_config.maxfee_percent),
exemptfee: None,
Expand Down
11 changes: 11 additions & 0 deletions libs/sdk-core/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -771,13 +771,24 @@ pub struct SendPaymentRequest {
pub amount_msat: Option<u64>,
}

/// Represents a TLV entry for a keysend payment.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TlvEntry {
/// The type field for the TLV
pub field_number: u64,
/// The value bytes for the TLV
pub value: Vec<u8>,
}

/// Represents a send spontaneous payment request.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SendSpontaneousPaymentRequest {
/// The node id to send this payment is
pub node_id: String,
/// The amount in millisatoshis for this payment
pub amount_msat: u64,
// Optional extra TLVs
pub extra_tlvs: Option<Vec<TlvEntry>>,
}

/// Represents a send payment response.
Expand Down
3 changes: 2 additions & 1 deletion libs/sdk-core/src/node_api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
invoice::InvoiceError, persist::error::PersistError, CustomMessage, MaxChannelAmount,
NodeCredentials, Payment, PaymentResponse, Peer, PrepareSweepRequest, PrepareSweepResponse,
RouteHintHop, SyncResponse,
RouteHintHop, SyncResponse, TlvEntry,
};
use anyhow::Result;
use bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
Expand Down Expand Up @@ -73,6 +73,7 @@ pub trait NodeAPI: Send + Sync {
&self,
node_id: String,
amount_msat: u64,
extra_tlvs: Option<Vec<TlvEntry>>,
) -> NodeResult<Payment>;
async fn start(&self) -> NodeResult<String>;

Expand Down
3 changes: 2 additions & 1 deletion libs/sdk-core/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::fiat::{FiatCurrency, Rate};
use crate::grpc::{PaymentInformation, RegisterPaymentNotificationResponse, RegisterPaymentReply};
use crate::invoice::{InvoiceError, InvoiceResult};
use crate::lsp::LspInformation;
use crate::models::{FiatAPI, LspAPI, NodeState, Payment, Swap, SwapperAPI, SyncResponse};
use crate::models::{FiatAPI, LspAPI, NodeState, Payment, Swap, SwapperAPI, SyncResponse, TlvEntry};
use crate::moonpay::MoonPayApi;
use crate::node_api::{NodeAPI, NodeError, NodeResult};
use crate::swap_in::error::SwapResult;
Expand Down Expand Up @@ -327,6 +327,7 @@ impl NodeAPI for MockNodeAPI {
&self,
_node_id: String,
_amount_msat: u64,
_extra_tlvs: Option<Vec<TlvEntry>>,
) -> NodeResult<Payment> {
let payment = self.add_dummy_payment_rand().await?;
Ok(payment)
Expand Down
66 changes: 66 additions & 0 deletions libs/sdk-flutter/lib/bridge_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1567,10 +1567,12 @@ class SendSpontaneousPaymentRequest {

/// The amount in millisatoshis for this payment
final int amountMsat;
final List<TlvEntry>? extraTlvs;

const SendSpontaneousPaymentRequest({
required this.nodeId,
required this.amountMsat,
this.extraTlvs,
});
}

Expand Down Expand Up @@ -1742,6 +1744,20 @@ class Symbol {
});
}

/// Represents a TLV entry for a keysend payment.
class TlvEntry {
/// The type field for the TLV
final int fieldNumber;

/// The value bytes for the TLV
final Uint8List value;

const TlvEntry({
required this.fieldNumber,
required this.value,
});
}

/// UTXO known to the LN node
class UnspentTransactionOutput {
final Uint8List txid;
Expand Down Expand Up @@ -4023,6 +4039,15 @@ class BreezSdkCorePlatform extends FlutterRustBridgeBase<BreezSdkCoreWire> {
return ans;
}

@protected
ffi.Pointer<wire_list_tlv_entry> api2wire_list_tlv_entry(List<TlvEntry> raw) {
final ans = inner.new_list_tlv_entry_0(raw.length);
for (var i = 0; i < raw.length; ++i) {
_api_fill_to_wire_tlv_entry(raw[i], ans.ref.ptr[i]);
}
return ans;
}

@protected
ffi.Pointer<wire_uint_8_list> api2wire_opt_String(String? raw) {
return raw == null ? ffi.nullptr : api2wire_String(raw);
Expand Down Expand Up @@ -4065,6 +4090,11 @@ class BreezSdkCorePlatform extends FlutterRustBridgeBase<BreezSdkCoreWire> {
return raw == null ? ffi.nullptr : api2wire_list_payment_type_filter(raw);
}

@protected
ffi.Pointer<wire_list_tlv_entry> api2wire_opt_list_tlv_entry(List<TlvEntry>? raw) {
return raw == null ? ffi.nullptr : api2wire_list_tlv_entry(raw);
}

@protected
ffi.Pointer<wire_uint_8_list> api2wire_opt_uint_8_list(Uint8List? raw) {
return raw == null ? ffi.nullptr : api2wire_uint_8_list(raw);
Expand Down Expand Up @@ -4395,6 +4425,7 @@ class BreezSdkCorePlatform extends FlutterRustBridgeBase<BreezSdkCoreWire> {
SendSpontaneousPaymentRequest apiObj, wire_SendSpontaneousPaymentRequest wireObj) {
wireObj.node_id = api2wire_String(apiObj.nodeId);
wireObj.amount_msat = api2wire_u64(apiObj.amountMsat);
wireObj.extra_tlvs = api2wire_opt_list_tlv_entry(apiObj.extraTlvs);
}

void _api_fill_to_wire_sign_message_request(SignMessageRequest apiObj, wire_SignMessageRequest wireObj) {
Expand All @@ -4409,6 +4440,11 @@ class BreezSdkCorePlatform extends FlutterRustBridgeBase<BreezSdkCoreWire> {
wireObj.to_address = api2wire_String(apiObj.toAddress);
wireObj.sat_per_vbyte = api2wire_u32(apiObj.satPerVbyte);
}

void _api_fill_to_wire_tlv_entry(TlvEntry apiObj, wire_TlvEntry wireObj) {
wireObj.field_number = api2wire_u64(apiObj.fieldNumber);
wireObj.value = api2wire_uint_8_list(apiObj.value);
}
}

// ignore_for_file: camel_case_types, non_constant_identifier_names, avoid_positional_boolean_parameters, annotate_overrides, constant_identifier_names
Expand Down Expand Up @@ -5554,6 +5590,20 @@ class BreezSdkCoreWire implements FlutterRustBridgeWireBase {
late final _new_list_payment_type_filter_0 = _new_list_payment_type_filter_0Ptr
.asFunction<ffi.Pointer<wire_list_payment_type_filter> Function(int)>();

ffi.Pointer<wire_list_tlv_entry> new_list_tlv_entry_0(
int len,
) {
return _new_list_tlv_entry_0(
len,
);
}

late final _new_list_tlv_entry_0Ptr =
_lookup<ffi.NativeFunction<ffi.Pointer<wire_list_tlv_entry> Function(ffi.Int32)>>(
'new_list_tlv_entry_0');
late final _new_list_tlv_entry_0 =
_new_list_tlv_entry_0Ptr.asFunction<ffi.Pointer<wire_list_tlv_entry> Function(int)>();

ffi.Pointer<wire_uint_8_list> new_uint_8_list_0(
int len,
) {
Expand Down Expand Up @@ -5704,11 +5754,27 @@ final class wire_SendPaymentRequest extends ffi.Struct {
external ffi.Pointer<ffi.Uint64> amount_msat;
}

final class wire_TlvEntry extends ffi.Struct {
@ffi.Uint64()
external int field_number;

external ffi.Pointer<wire_uint_8_list> value;
}

final class wire_list_tlv_entry extends ffi.Struct {
external ffi.Pointer<wire_TlvEntry> ptr;

@ffi.Int32()
external int len;
}

final class wire_SendSpontaneousPaymentRequest extends ffi.Struct {
external ffi.Pointer<wire_uint_8_list> node_id;

@ffi.Uint64()
external int amount_msat;

external ffi.Pointer<wire_list_tlv_entry> extra_tlvs;
}

final class wire_OpeningFeeParams extends ffi.Struct {
Expand Down
Loading

0 comments on commit 57e6d2d

Please sign in to comment.