use std::net::SocketAddr;
use reqwest::Client;
#[cfg(not(target_arch = "wasm32"))]
use reqwest::Proxy;
use serde::{Deserialize, Serialize};
use crate::error::Error;
use crate::lud06::LnUrl;
use crate::lud16::LightningAddress;
#[derive(Serialize, Deserialize)]
enum TagRequest {
#[serde(rename = "payRequest")]
Pay,
#[serde(rename = "withdrawRequest")]
Withdraw,
#[serde(rename = "channelRequest")]
Channel,
}
#[derive(Serialize, Deserialize)]
struct PayResponse {
pub callback: String,
#[serde(rename = "maxSendable")]
pub max_sendable: u64,
#[serde(rename = "minSendable")]
pub min_sendable: u64,
pub tag: TagRequest,
pub metadata: String,
#[serde(rename = "allowsNostr")]
pub allows_nostr: Option<bool>,
}
pub enum Lud06OrLud16 {
Lud06(LnUrl),
Lud16(LightningAddress),
}
impl Lud06OrLud16 {
pub fn endpoint(&self) -> String {
match self {
Self::Lud06(v) => v.endpoint(),
Self::Lud16(v) => v.endpoint(),
}
}
}
impl From<LnUrl> for Lud06OrLud16 {
fn from(value: LnUrl) -> Self {
Self::Lud06(value)
}
}
impl From<LightningAddress> for Lud06OrLud16 {
fn from(value: LightningAddress) -> Self {
Self::Lud16(value)
}
}
pub async fn get_invoice<S>(
lud: S,
msats: u64,
zap_request: Option<String>,
_proxy: Option<SocketAddr>,
) -> Result<String, Error>
where
S: Into<Lud06OrLud16>,
{
#[cfg(not(target_arch = "wasm32"))]
let client: Client = {
let mut builder = Client::builder();
if let Some(proxy) = _proxy {
let proxy = format!("socks5h://{proxy}");
builder = builder.proxy(Proxy::all(proxy)?);
}
builder.build()?
};
#[cfg(target_arch = "wasm32")]
let client: Client = Client::new();
let lud: Lud06OrLud16 = lud.into();
let endpoint: String = lud.endpoint();
let resp = client.get(endpoint).send().await?;
let pay_response: PayResponse = resp.error_for_status()?.json().await?;
let symbol: &str = if pay_response.callback.contains('?') {
"&"
} else {
"?"
};
let url = match zap_request {
Some(zap_request) => format!(
"{}{}amount={}&nostr={}",
pay_response.callback, symbol, msats, zap_request
),
None => format!("{}{}amount={}", pay_response.callback, symbol, msats),
};
let resp = client.get(&url).send().await?;
Ok(resp.error_for_status()?.json().await?)
}