Skip to content

Commit

Permalink
add trampoline client support
Browse files Browse the repository at this point in the history
extract trampoline payment data from label
  • Loading branch information
JssDWt committed Aug 15, 2024
1 parent 69a3f98 commit 75a21b3
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 7 deletions.
76 changes: 69 additions & 7 deletions libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use gl_client::pb::cln::{
};
use gl_client::pb::scheduler::scheduler_client::SchedulerClient;
use gl_client::pb::scheduler::{NodeInfoRequest, UpgradeRequest};
use gl_client::pb::{OffChainPayment, PayStatus};
use gl_client::pb::{OffChainPayment, PayStatus, TrampolinePayRequest};
use gl_client::scheduler::Scheduler;
use gl_client::signer::model::greenlight::{amount, scheduler};
use gl_client::signer::{Error, Signer};
Expand Down Expand Up @@ -72,6 +72,14 @@ struct InvoiceLabel {
pub payer_amount_msat: Option<u64>,
}

#[derive(Serialize, Deserialize)]
struct PaymentLabel {
pub unix_nano: u128,
pub trampoline: bool,
pub client_label: Option<String>,
pub amount_msat: u64,
}

impl Greenlight {
/// Connects to a live node using the provided seed and config.
/// If the node is not registered, it will try to recover it using the seed.
Expand Down Expand Up @@ -1147,6 +1155,47 @@ impl NodeAPI for Greenlight {
payment.try_into()
}

async fn send_trampoline_payment(
&self,
bolt11: String,
amount_msat: u64,
label: Option<String>,
trampoline_node_id: Vec<u8>,
) -> NodeResult<Payment> {
let invoice = parse_invoice(&bolt11)?;
validate_network(invoice.clone(), self.sdk_config.network)?;
let label = serde_json::to_string(&PaymentLabel {
trampoline: true,
client_label: label,
unix_nano: SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos(),
amount_msat,
})?;
let mut client = self.get_client().await?;
let request = TrampolinePayRequest {
bolt11,
trampoline_node_id,
amount_msat,
label,
maxdelay: u32::default(),
description: String::default(),
maxfeepercent: f32::default(),
};
let result = self
.with_keep_alive(client.trampoline_pay(request))
.await?
.into_inner();

let client = self.get_node_client().await?;

// Before returning from send_payment we need to make sure it is
// persisted in the backend node. We do so by polling for the payment.
// TODO: Ensure this works with trampoline payments
// NOTE: If this doesn't work with trampoline payments, the sync also
// needs updating.
let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
payment.try_into()
}

async fn send_spontaneous_payment(
&self,
node_id: String,
Expand Down Expand Up @@ -2114,16 +2163,29 @@ impl TryFrom<cln::ListpaysPays> for Payment {
.as_ref()
.ok_or(InvoiceError::generic("No bolt11 invoice"))
.and_then(|b| parse_invoice(b));
let payment_amount = payment
.amount_msat
.clone()
.map(|a| a.msat)
.unwrap_or_default();
let payment_amount_sent = payment
.amount_sent_msat
.clone()
.map(|a| a.msat)
.unwrap_or_default();

// For trampoline payments the amount_msat doesn't match the actual
// amount. If it's a trampoline payment, take the amount from the label.
let (payment_amount, client_label) = serde_json::from_str::<PaymentLabel>(payment.label())
.ok()
.and_then(|label| {
label
.trampoline
.then_some((label.amount_msat, label.client_label))
})
.unwrap_or((
payment
.amount_msat
.clone()
.map(|a| a.msat)
.unwrap_or_default(),
payment.label.clone(),
));
let status = payment.status().into();

Ok(Payment {
Expand All @@ -2143,7 +2205,7 @@ impl TryFrom<cln::ListpaysPays> for Payment {
details: PaymentDetails::Ln {
data: LnPaymentDetails {
payment_hash: hex::encode(payment.payment_hash),
label: payment.label.unwrap_or_default(),
label: client_label.unwrap_or_default(),
destination_pubkey: payment.destination.map(hex::encode).unwrap_or_default(),
payment_preimage: payment.preimage.map(hex::encode).unwrap_or_default(),
keysend: payment.bolt11.is_none(),
Expand Down
7 changes: 7 additions & 0 deletions libs/sdk-core/src/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ pub trait NodeAPI: Send + Sync {
extra_tlvs: Option<Vec<TlvEntry>>,
label: Option<String>,
) -> NodeResult<Payment>;
async fn send_trampoline_payment(
&self,
bolt11: String,
amount_msat: u64,
label: Option<String>,
trampoline_node_id: Vec<u8>,
) -> NodeResult<Payment>;
async fn start(&self) -> NodeResult<String>;

/// Attempts to find a payment path "manually" and send the htlcs in a way that will drain
Expand Down
11 changes: 11 additions & 0 deletions libs/sdk-core/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ impl NodeAPI for MockNodeAPI {
Ok(payment)
}

async fn send_trampoline_payment(
&self,
bolt11: String,
_amount_msat: u64,
_label: Option<String>,
_trampoline_id: Vec<u8>,
) -> NodeResult<Payment> {
let payment = self.add_dummy_payment_for(bolt11, None, None).await?;
Ok(payment)
}

async fn send_spontaneous_payment(
&self,
_node_id: String,
Expand Down

0 comments on commit 75a21b3

Please sign in to comment.