diff --git a/src/lightning.rs b/src/lightning.rs index 65cfe24..c0d11b4 100644 --- a/src/lightning.rs +++ b/src/lightning.rs @@ -2,10 +2,15 @@ use serde::{Deserialize, Serialize}; use bitcoin_waila::PaymentParams; use lightning_invoice::Bolt11Invoice; +use lnurl::lightning_address::LightningAddress; +use lnurl::lnurl::LnUrl; use lnurl::LnUrlResponse; +use nostr::prelude::ZapRequestData; +use nostr::{EventBuilder, Filter, JsonUtil, Kind, Metadata, UncheckedUrl}; use std::str::FromStr; use tonic_openssl_lnd::lnrpc; +use crate::nostr_dms::RELAYS; use crate::{AppState, MAX_SEND_AMOUNT}; #[derive(Clone, Deserialize)] @@ -44,6 +49,48 @@ pub async fn pay_lightning(state: AppState, bolt11: &str) -> anyhow::Result anyhow::bail!("invalid lnurl"), } + } else if let Some(npub) = params.nostr_pubkey() { + let client = nostr_sdk::Client::default(); + client.add_relays(RELAYS).await?; + client.connect().await; + + let filter = Filter::new() + .author(npub.into()) + .kind(Kind::Metadata) + .limit(1); + let events = client.get_events_of(vec![filter], None).await?; + let event = events + .into_iter() + .max_by_key(|e| e.created_at) + .ok_or(anyhow::anyhow!("no event"))?; + + let metadata = Metadata::from_json(&event.content)?; + let lnurl = metadata + .lud16 + .and_then(|l| LightningAddress::from_str(&l).ok().map(|l| l.lnurl())) + .or(metadata.lud06.and_then(|l| LnUrl::decode(l).ok())) + .ok_or(anyhow::anyhow!("no lnurl"))?; + + match state.lnurl.make_request(&lnurl.url).await? { + LnUrlResponse::LnUrlPayResponse(pay) => { + if pay.min_sendable > MAX_SEND_AMOUNT { + anyhow::bail!("max amount is 10,000,000"); + } + + let relays = RELAYS.iter().map(|r| UncheckedUrl::new(*r)); + let zap_data = ZapRequestData::new(npub.into(), relays) + .lnurl(lnurl.encode()) + .amount(pay.min_sendable); + let zap = EventBuilder::public_zap_request(zap_data).to_event(&state.keys)?; + + let inv = state + .lnurl + .get_invoice(&pay, pay.min_sendable, Some(zap.as_json()), None) + .await?; + Bolt11Invoice::from_str(inv.invoice())? + } + _ => anyhow::bail!("invalid lnurl"), + } } else { anyhow::bail!("invalid bolt11") }; diff --git a/src/nostr_dms.rs b/src/nostr_dms.rs index c51b451..819f71f 100644 --- a/src/nostr_dms.rs +++ b/src/nostr_dms.rs @@ -9,7 +9,7 @@ use nostr_sdk::{Client, RelayPoolNotification}; use std::str::FromStr; use tonic_openssl_lnd::lnrpc; -const RELAYS: [&str; 8] = [ +pub const RELAYS: [&str; 8] = [ "wss://nostr.mutinywallet.com", "wss://relay.mutinywallet.com", "wss://relay.primal.net",