LNURL-Pay
Preparing LNURL Payments
During the prepare step, the SDK ensures that the inputs are valid with respect to the LNURL-pay request, and also returns the relative fees related to the payment so they can be confirmed. If the LNURL-pay invoice includes a Magic Routing Hint for a direct Liquid payment, the fees will reflect this.
Rust
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
let lnurl_pay_url = "lightning@address.com";
if let Ok(InputType::LnUrlPay { data: pd }) = parse(lnurl_pay_url).await {
let amount_msat = pd.min_sendable;
let optional_comment = Some("<comment>".to_string());
let optional_validate_success_action_url = Some(true);
let prepare_response = sdk.prepare_lnurl_pay(PrepareLnUrlPayRequest {
data: pd,
amount_msat,
comment: optional_comment,
validate_success_action_url: optional_validate_success_action_url,
})
.await?;
// If the fees are acceptable, continue to create the LNURL Pay
let fees_sat = prepare_response.fees_sat;
info!("Fees: {} sats", fees_sat);
}
Swift
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
var response: LnUrlPayResult?
let lnurlPayUrl = "lightning@address.com"
if let inputType = try? parse(input: lnurlPayUrl) {
if case.lnUrlPay(let `data`) = inputType {
let amountMsat = data.minSendable
let optionalComment = "<comment>"
let optionalValidateSuccessActionUrl = true
let req = PrepareLnUrlPayRequest(
data: data,
amountMsat: amountMsat,
comment: optionalComment,
validateSuccessActionUrl: optionalValidateSuccessActionUrl
)
let prepareResponse = try? sdk.prepareLnurlPay(req: req)
// If the fees are acceptable, continue to create the LNURL Pay
let feesSat = prepareResponse!.feesSat
print("Fees: {} sats", feesSat);
}
}
Kotlin
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
val lnurlPayUrl = "lightning@address.com";
try {
val inputType = parse(lnurlPayUrl)
if (inputType is InputType.LnUrlPay) {
val requestData = inputType.data
val amountMsat = requestData.minSendable
val optionalComment = "<comment>";
val optionalValidateSuccessActionUrl = true;
val req = PrepareLnUrlPayRequest(
requestData,
amountMsat,
optionalComment,
optionalValidateSuccessActionUrl)
val prepareResponse = sdk.prepareLnurlPay(req)
// If the fees are acceptable, continue to create the LNURL Pay
val feesSat = prepareResponse.feesSat;
// Log.v("Breez", "Fees: ${feesSat} sats")
}
} catch (e: Exception) {
// handle error
}
React Native
// Endpoint can also be of the
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
const lnurlPayUrl = 'lightning@address.com'
const input = await parse(lnurlPayUrl)
if (input.type === InputTypeVariant.LN_URL_PAY) {
const amountMsat = input.data.minSendable
const optionalComment = '<comment>'
const optionalValidateSuccessActionUrl = true
const prepareResponse = await prepareLnurlPay({
data: input.data,
amountMsat,
comment: optionalComment,
validateSuccessActionUrl: optionalValidateSuccessActionUrl
})
// If the fees are acceptable, continue to create the LNURL Pay
const feesSat = prepareResponse.feesSat
console.log(`Fees: ${feesSat} sats`)
}
Dart
/// Endpoint can also be of the form:
/// lnurlp://domain.com/lnurl-pay?key=val
/// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
String lnurlPayUrl = "lightning@address.com";
InputType inputType = await parse(input: lnurlPayUrl);
if (inputType is InputType_LnUrlPay) {
BigInt amountMsat = inputType.data.minSendable;
String optionalComment = "<comment>";
bool optionalValidateSuccessActionUrl = true;
PrepareLnUrlPayRequest req = PrepareLnUrlPayRequest(
data: inputType.data,
amountMsat: amountMsat,
comment: optionalComment,
validateSuccessActionUrl: optionalValidateSuccessActionUrl,
);
PrepareLnUrlPayResponse prepareResponse = await breezSDKLiquid.instance!.prepareLnurlPay(req: req);
// If the fees are acceptable, continue to create the LNURL Pay
BigInt feesSat = prepareResponse.feesSat;
print("Fees: $feesSat sats");
}
Python
# Endpoint can also be of the form:
# lnurlp://domain.com/lnurl-pay?key=val
# lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
lnurl_pay_url = "lightning@address.com"
try:
parsed_input = breez_sdk_liquid.parse(lnurl_pay_url)
if isinstance(parsed_input, InputType.LN_URL_PAY):
amount_msat = parsed_input.data.min_sendable
optional_comment = "<comment>"
optional_validate_success_action_url = True
req = PrepareLnUrlPayRequest(parsed_input.data,
amount_msat,
optional_comment,
optional_validate_success_action_url)
prepare_response = sdk.prepare_lnurl_pay(req)
# If the fees are acceptable, continue to create the LNURL Pay
fees_sat = prepare_response.fees_sat
logging.debug("Fees: ", fees_sat, " sats")
return prepare_response
except Exception as error:
logging.error(error)
raise
Go
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
lnurlPayUrl := "lightning@address.com"
if input, err := breez_sdk_liquid.Parse(lnurlPayUrl); err != nil {
switch inputType := input.(type) {
case breez_sdk_liquid.InputTypeLnUrlPay:
amountMsat := inputType.Data.MinSendable
optionalComment := "<comment>"
optionalValidateSuccessActionUrl := true
req := breez_sdk_liquid.PrepareLnUrlPayRequest{
Data: inputType.Data,
AmountMsat: amountMsat,
Comment: &optionalComment,
ValidateSuccessActionUrl: &optionalValidateSuccessActionUrl,
}
prepareResponse, err := sdk.PrepareLnurlPay(req)
if err != nil {
log.Printf("Error: %#v", err)
return
}
// If the fees are acceptable, continue to create the LNURL Pay
feesSat := prepareResponse.FeesSat
log.Printf("Fees: %v sats", feesSat)
}
}
C#
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
var lnurlPayUrl = "lightning@address.com";
try
{
var input = BreezSdkLiquidMethods.Parse(lnurlPayUrl);
if (input is InputType.LnUrlPay lnurlp)
{
var amountMsat = lnurlp.data.minSendable;
var optionalComment = "<comment>";
var optionalValidateSuccessActionUrl = true;
var req = new PrepareLnUrlPayRequest(
lnurlp.data,
amountMsat,
optionalComment,
optionalValidateSuccessActionUrl);
var prepareResponse = sdk.PrepareLnurlPay(req);
// If the fees are acceptable, continue to create the LNURL Pay
var feesSat = prepareResponse.feesSat;
Console.WriteLine($"Fees: {feesSat} sats");
}
}
catch (Exception)
{
// Handle error
}
LNURL Payments
Once the payment has been prepared and the fees are accepted, all you have to do is pass the prepare response as an argument to the LNURL pay method.
Rust
let result = sdk
.lnurl_pay(LnUrlPayRequest { prepare_response })
.await?;
Swift
let result = try? sdk.lnurlPay(req: LnUrlPayRequest (
prepareResponse: prepareResponse
))
Kotlin
try {
val result = sdk.lnurlPay(LnUrlPayRequest(prepareResponse))
} catch (e: Exception) {
// handle error
}
React Native
const result = await lnurlPay({
prepareResponse
})
Dart
LnUrlPayResult result = await breezSDKLiquid.instance!.lnurlPay(
req: LnUrlPayRequest(prepareResponse: prepareResponse),
);
Python
try:
result = sdk.lnurl_pay(LnUrlPayRequest(prepare_response))
except Exception as error:
logging.error(error)
raise
Go
req := breez_sdk_liquid.LnUrlPayRequest{
PrepareResponse: prepareResponse,
}
if result, err := sdk.LnurlPay(req); err != nil {
log.Printf("Result: %#v", result)
}
C#
try
{
var result = sdk.LnurlPay(new LnUrlPayRequest(prepareResponse));
}
catch (Exception)
{
// Handle error
}
Developer note
By default when the LNURL-pay results in a success action with a URL, the URL is validated to check if there is a mismatch with the LNURL callback domain. You can disable this behaviour by setting the optional validationPrepareLnUrlPayRequest
param to false.