Skip to content

Commit b6a2a19

Browse files
committed
Pay to npub
1 parent 786cf72 commit b6a2a19

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

src/lightning.rs

+47
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ use serde::{Deserialize, Serialize};
22

33
use bitcoin_waila::PaymentParams;
44
use lightning_invoice::Bolt11Invoice;
5+
use lnurl::lightning_address::LightningAddress;
6+
use lnurl::lnurl::LnUrl;
57
use lnurl::LnUrlResponse;
8+
use nostr::prelude::ZapRequestData;
9+
use nostr::{EventBuilder, Filter, JsonUtil, Kind, Metadata, UncheckedUrl};
610
use std::str::FromStr;
711
use tonic_openssl_lnd::lnrpc;
812

13+
use crate::nostr_dms::RELAYS;
914
use crate::{AppState, MAX_SEND_AMOUNT};
1015

1116
#[derive(Clone, Deserialize)]
@@ -44,6 +49,48 @@ pub async fn pay_lightning(state: AppState, bolt11: &str) -> anyhow::Result<Stri
4449
}
4550
_ => anyhow::bail!("invalid lnurl"),
4651
}
52+
} else if let Some(npub) = params.nostr_pubkey() {
53+
let client = nostr_sdk::Client::default();
54+
client.add_relays(RELAYS).await?;
55+
client.connect().await;
56+
57+
let filter = Filter::new()
58+
.author(npub.into())
59+
.kind(Kind::Metadata)
60+
.limit(1);
61+
let events = client.get_events_of(vec![filter], None).await?;
62+
let event = events
63+
.into_iter()
64+
.max_by_key(|e| e.created_at)
65+
.ok_or(anyhow::anyhow!("no event"))?;
66+
67+
let metadata = Metadata::from_json(&event.content)?;
68+
let lnurl = metadata
69+
.lud16
70+
.and_then(|l| LightningAddress::from_str(&l).ok().map(|l| l.lnurl()))
71+
.or(metadata.lud06.and_then(|l| LnUrl::decode(l).ok()))
72+
.ok_or(anyhow::anyhow!("no lnurl"))?;
73+
74+
match state.lnurl.make_request(&lnurl.url).await? {
75+
LnUrlResponse::LnUrlPayResponse(pay) => {
76+
if pay.min_sendable > MAX_SEND_AMOUNT {
77+
anyhow::bail!("max amount is 10,000,000");
78+
}
79+
80+
let relays = RELAYS.iter().map(|r| UncheckedUrl::new(*r));
81+
let zap_data = ZapRequestData::new(npub.into(), relays)
82+
.lnurl(lnurl.encode())
83+
.amount(pay.min_sendable);
84+
let zap = EventBuilder::public_zap_request(zap_data).to_event(&state.keys)?;
85+
86+
let inv = state
87+
.lnurl
88+
.get_invoice(&pay, pay.min_sendable, Some(zap.as_json()), None)
89+
.await?;
90+
Bolt11Invoice::from_str(inv.invoice())?
91+
}
92+
_ => anyhow::bail!("invalid lnurl"),
93+
}
4794
} else {
4895
anyhow::bail!("invalid bolt11")
4996
};

src/nostr_dms.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use nostr_sdk::{Client, RelayPoolNotification};
99
use std::str::FromStr;
1010
use tonic_openssl_lnd::lnrpc;
1111

12-
const RELAYS: [&str; 8] = [
12+
pub const RELAYS: [&str; 8] = [
1313
"wss://nostr.mutinywallet.com",
1414
"wss://relay.mutinywallet.com",
1515
"wss://relay.primal.net",

0 commit comments

Comments
 (0)