Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sdk-common: Expose if BIP353 is used for parsing #1164

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libs/sdk-bindings/src/breez_sdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ interface InputType {
Bolt11(LNInvoice invoice);
NodeId(string node_id);
Url(string url);
LnUrlPay(LnUrlPayRequestData data);
LnUrlPay(LnUrlPayRequestData data, string? bip353_address);
LnUrlWithdraw(LnUrlWithdrawRequestData data);
LnUrlAuth(LnUrlAuthRequestData data);
LnUrlError(LnUrlErrorData data);
Expand Down
63 changes: 45 additions & 18 deletions libs/sdk-common/src/input_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::ops::Not;
use std::str::FromStr;

use ::bip21::Uri;
use anyhow::{anyhow, Context, Result};
use anyhow::{anyhow, bail, Context, Result};
use bitcoin::bech32;
use bitcoin::bech32::FromBase32;
use hickory_resolver::config::{ResolverConfig, ResolverOpts};
Expand Down Expand Up @@ -117,11 +117,11 @@ lazy_static! {
/// async fn main() -> Result<()> {
/// let lnurl_pay_url = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf";
///
/// assert!(matches!( parse(lnurl_pay_url, None).await, Ok(LnUrlPay{data: _}) ));
/// assert!(matches!( parse(lnurl_pay_url, None).await, Ok(LnUrlPay{data: _, bip353_address: _}) ));
/// // assert!(matches!( parse("lnurlp://domain.com/lnurl-pay?key=val").await, Ok(LnUrlPay{data: _}) ));
/// // assert!(matches!( parse("[email protected]").await, Ok(LnUrlPay{data: _}) ));
///
/// if let Ok(LnUrlPay{data: pd}) = parse(lnurl_pay_url,None).await {
/// if let Ok(LnUrlPay{data: pd, bip353_address}) = parse(lnurl_pay_url,None).await {
/// assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
/// assert_eq!(pd.max_sendable, 16000); // Max sendable amount, in msats
/// assert_eq!(pd.max_sendable_sats(), 16); // Max sendable amount, in sats
Expand Down Expand Up @@ -206,14 +206,29 @@ pub async fn parse(
let input = input.trim();

// Try to parse the destination as a bip353 address.
let input_parsed = match bip353_parse(input, &DNS_RESOLVER).await {
Some(value) => value,
None => input.to_string(),
let (bip353_parsed_input, is_bip353) = match bip353_parse(input, &DNS_RESOLVER).await {
Some(value) => (value, true),
None => (input.to_string(), false),
};

let input = input_parsed.as_str();
if let Ok(input_type) = parse_core(&bip353_parsed_input).await {
let input_type = if is_bip353 {
match input_type {
#[cfg(feature = "liquid")]
InputType::Bolt12Offer { offer, .. } => InputType::Bolt12Offer {
offer,
bip353_address: Some(input.to_string()),
},
InputType::LnUrlPay { data, .. } => InputType::LnUrlPay {
data,
bip353_address: Some(input.to_string()),
},
i => bail!("Unexpected input type was resolved from a BIP353 address: {i:?}"),
}
} else {
input_type
};

if let Ok(input_type) = parse_core(input).await {
return Ok(input_type);
}

Expand Down Expand Up @@ -325,7 +340,10 @@ async fn parse_core(input: &str) -> Result<InputType> {

#[cfg(feature = "liquid")]
if let Ok(offer) = parse_bolt12_offer(input) {
return Ok(InputType::Bolt12Offer { offer });
return Ok(InputType::Bolt12Offer {
offer,
bip353_address: None,
});
}

if let Ok(invoice) = parse_invoice(input) {
Expand Down Expand Up @@ -412,8 +430,9 @@ async fn parse_external(
let input_type = lnurl_data.into();
let input_type = match input_type {
// Modify the LnUrlPay payload by adding the domain of the LNURL endpoint
InputType::LnUrlPay { data } => InputType::LnUrlPay {
InputType::LnUrlPay { data, .. } => InputType::LnUrlPay {
data: LnUrlPayRequestData { domain, ..data },
bip353_address: None,
},
_ => input_type,
};
Expand Down Expand Up @@ -588,12 +607,13 @@ async fn resolve_lnurl(
let temp = lnurl_data.into();
let temp = match temp {
// Modify the LnUrlPay payload by adding the domain of the LNURL endpoint
InputType::LnUrlPay { data } => InputType::LnUrlPay {
InputType::LnUrlPay { data, .. } => InputType::LnUrlPay {
data: LnUrlPayRequestData {
domain,
ln_address,
..data
},
bip353_address: None,
},
_ => temp,
};
Expand Down Expand Up @@ -628,6 +648,8 @@ pub enum InputType {
#[cfg(feature = "liquid")]
Bolt12Offer {
offer: LNOffer,
/// The BIP353 address in case one was resolved
erdemyerebasmaz marked this conversation as resolved.
Show resolved Hide resolved
bip353_address: Option<String>,
},
NodeId {
node_id: String,
Expand All @@ -644,6 +666,8 @@ pub enum InputType {
/// - LUD-17 Support for lnurlp prefix with non-bech32-encoded LNURL URLs
LnUrlPay {
data: LnUrlPayRequestData,
/// The BIP353 address in case one was resolved
bip353_address: Option<String>,
},

/// # Supported standards
Expand Down Expand Up @@ -705,7 +729,10 @@ pub enum LnUrlRequestData {
impl From<LnUrlRequestData> for InputType {
fn from(lnurl_data: LnUrlRequestData) -> Self {
match lnurl_data {
PayRequest { data } => Self::LnUrlPay { data },
PayRequest { data } => Self::LnUrlPay {
data,
bip353_address: None,
},
WithdrawRequest { data } => Self::LnUrlWithdraw { data },
AuthRequest { data } => Self::LnUrlAuth { data },
Error { data } => Self::LnUrlError { data },
Expand Down Expand Up @@ -1568,7 +1595,7 @@ pub(crate) mod tests {
("localhost".into(), format!("https://localhost{path}"), None)
);

if let InputType::LnUrlPay { data: pd } = parse(lnurl_pay_encoded, None).await? {
if let InputType::LnUrlPay { data: pd, .. } = parse(lnurl_pay_encoded, None).await? {
assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
assert_eq!(pd.max_sendable, 16000);
assert_eq!(pd.min_sendable, 4000);
Expand Down Expand Up @@ -1608,7 +1635,7 @@ pub(crate) mod tests {
] {
assert!(matches!(
parse(lnurl_pay, None).await?,
InputType::LnUrlPay { data: _ }
InputType::LnUrlPay { .. }
));
}
Ok(())
Expand All @@ -1622,7 +1649,7 @@ pub(crate) mod tests {
let ln_address = "[email protected]";
let _m = mock_lnurl_ln_address_endpoint(ln_address, None)?;

if let InputType::LnUrlPay { data: pd } = parse(ln_address, None).await? {
if let InputType::LnUrlPay { data: pd, .. } = parse(ln_address, None).await? {
assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
assert_eq!(pd.max_sendable, 16000);
assert_eq!(pd.min_sendable, 4000);
Expand Down Expand Up @@ -1665,7 +1692,7 @@ pub(crate) mod tests {
let server_ln_address = "[email protected]";
let _m = mock_lnurl_ln_address_endpoint(server_ln_address, None)?;

if let InputType::LnUrlPay { data: pd } = parse(ln_address, None).await? {
if let InputType::LnUrlPay { data: pd, .. } = parse(ln_address, None).await? {
assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
assert_eq!(pd.max_sendable, 16000);
assert_eq!(pd.min_sendable, 4000);
Expand Down Expand Up @@ -1871,7 +1898,7 @@ pub(crate) mod tests {
let _m = mock_lnurl_pay_endpoint(pay_path, None);

let lnurl_pay_url = format!("lnurlp://localhost{pay_path}");
if let InputType::LnUrlPay { data: pd } = parse(&lnurl_pay_url, None).await? {
if let InputType::LnUrlPay { data: pd, .. } = parse(&lnurl_pay_url, None).await? {
assert_eq!(pd.callback, "https://localhost/lnurl-pay/callback/db945b624265fc7f5a8d77f269f7589d789a771bdfd20e91a3cf6f50382a98d7");
assert_eq!(pd.max_sendable, 16000);
assert_eq!(pd.min_sendable, 4000);
Expand Down Expand Up @@ -2007,7 +2034,7 @@ pub(crate) mod tests {
}];

let input_type = parse(input, Some(&parsers)).await?;
if let InputType::LnUrlPay { data } = input_type {
if let InputType::LnUrlPay { data, .. } = input_type {
assert_eq!(data.callback, "callback_url");
assert_eq!(data.max_sendable, 57000);
assert_eq!(data.min_sendable, 57000);
Expand Down
33 changes: 25 additions & 8 deletions libs/sdk-core/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,31 @@ pub struct _LnUrlWithdrawRequestData {

#[frb(mirror(InputType))]
pub enum _InputType {
BitcoinAddress { address: BitcoinAddressData },
Bolt11 { invoice: LNInvoice },
NodeId { node_id: String },
Url { url: String },
LnUrlPay { data: LnUrlPayRequestData },
LnUrlWithdraw { data: LnUrlWithdrawRequestData },
LnUrlAuth { data: LnUrlAuthRequestData },
LnUrlError { data: LnUrlErrorData },
BitcoinAddress {
address: BitcoinAddressData,
},
Bolt11 {
invoice: LNInvoice,
},
NodeId {
node_id: String,
},
Url {
url: String,
},
LnUrlPay {
data: LnUrlPayRequestData,
bip353_address: Option<String>,
},
LnUrlWithdraw {
data: LnUrlWithdrawRequestData,
},
LnUrlAuth {
data: LnUrlAuthRequestData,
},
LnUrlError {
data: LnUrlErrorData,
},
}

#[frb(mirror(BitcoinAddressData))]
Expand Down
15 changes: 13 additions & 2 deletions libs/sdk-core/src/bridge_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,8 +1009,12 @@ const _: fn() = || {
InputType::Url { url } => {
let _: String = url;
}
InputType::LnUrlPay { data } => {
InputType::LnUrlPay {
data,
bip353_address,
} => {
let _: LnUrlPayRequestData = data;
let _: Option<String> = bip353_address;
}
InputType::LnUrlWithdraw { data } => {
let _: LnUrlWithdrawRequestData = data;
Expand Down Expand Up @@ -1608,7 +1612,14 @@ impl support::IntoDart for mirror_InputType {
vec![2.into_dart(), node_id.into_into_dart().into_dart()]
}
InputType::Url { url } => vec![3.into_dart(), url.into_into_dart().into_dart()],
InputType::LnUrlPay { data } => vec![4.into_dart(), data.into_into_dart().into_dart()],
InputType::LnUrlPay {
data,
bip353_address,
} => vec![
4.into_dart(),
data.into_into_dart().into_dart(),
bip353_address.into_dart(),
],
InputType::LnUrlWithdraw { data } => {
vec![5.into_dart(), data.into_into_dart().into_dart()]
}
Expand Down
2 changes: 2 additions & 0 deletions libs/sdk-flutter/lib/bridge_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ sealed class InputType with _$InputType {
}) = InputType_Url;
const factory InputType.lnUrlPay({
required LnUrlPayRequestData data,
String? bip353Address,
}) = InputType_LnUrlPay;
const factory InputType.lnUrlWithdraw({
required LnUrlWithdrawRequestData data,
Expand Down Expand Up @@ -3378,6 +3379,7 @@ class BreezSdkCoreImpl implements BreezSdkCore {
case 4:
return InputType_LnUrlPay(
data: _wire2api_box_autoadd_ln_url_pay_request_data(raw[1]),
bip353Address: _wire2api_opt_String(raw[2]),
);
case 5:
return InputType_LnUrlWithdraw(
Expand Down
Loading
Loading