Files
api/lnvps_api/src/lightning/lnd.rs
Kieran 9296e571ec
All checks were successful
continuous-integration/drone/push Build is passing
refactor: convert to workspace
2025-04-02 13:18:18 +01:00

93 lines
2.9 KiB
Rust

use crate::lightning::{AddInvoiceRequest, AddInvoiceResult, InvoiceUpdate, LightningNode};
use anyhow::Result;
use fedimint_tonic_lnd::invoicesrpc::lookup_invoice_msg::InvoiceRef;
use fedimint_tonic_lnd::invoicesrpc::LookupInvoiceMsg;
use fedimint_tonic_lnd::lnrpc::invoice::InvoiceState;
use fedimint_tonic_lnd::lnrpc::{Invoice, InvoiceSubscription};
use fedimint_tonic_lnd::{connect, Client};
use futures::StreamExt;
use lnvps_db::async_trait;
use nostr_sdk::async_utility::futures_util::Stream;
use std::path::Path;
use std::pin::Pin;
pub struct LndNode {
client: Client,
}
impl LndNode {
pub async fn new(url: &str, cert: &Path, macaroon: &Path) -> Result<Self> {
let lnd = connect(url.to_string(), cert, macaroon).await?;
Ok(Self { client: lnd })
}
}
#[async_trait]
impl LightningNode for LndNode {
async fn add_invoice(&self, req: AddInvoiceRequest) -> Result<AddInvoiceResult> {
let mut client = self.client.clone();
let ln = client.lightning();
let res = ln
.add_invoice(Invoice {
memo: req.memo.unwrap_or_default(),
value_msat: req.amount as i64,
expiry: req.expire.unwrap_or(3600) as i64,
..Default::default()
})
.await?;
let inner = res.into_inner();
Ok(AddInvoiceResult {
pr: inner.payment_request,
payment_hash: hex::encode(inner.r_hash),
external_id: None,
})
}
async fn subscribe_invoices(
&self,
from_payment_hash: Option<Vec<u8>>,
) -> Result<Pin<Box<dyn Stream<Item = InvoiceUpdate> + Send>>> {
let mut client = self.client.clone();
let from_settle_index = if let Some(ph) = from_payment_hash {
if let Ok(inv) = client
.invoices()
.lookup_invoice_v2(LookupInvoiceMsg {
lookup_modifier: 0,
invoice_ref: Some(InvoiceRef::PaymentHash(ph)),
})
.await
{
inv.into_inner().settle_index
} else {
0
}
} else {
0
};
let stream = client
.lightning()
.subscribe_invoices(InvoiceSubscription {
add_index: 0,
settle_index: from_settle_index,
})
.await?;
let stream = stream.into_inner();
Ok(Box::pin(stream.map(|i| match i {
Ok(m) => {
if m.state == InvoiceState::Settled as i32 {
InvoiceUpdate::Settled {
payment_hash: Some(hex::encode(m.r_hash)),
external_id: None,
}
} else {
InvoiceUpdate::Unknown
}
}
Err(e) => InvoiceUpdate::Error(e.to_string()),
})))
}
}