Skip to content

Commit

Permalink
Add a specific failure notification if the fee limit causes payment i…
Browse files Browse the repository at this point in the history
…ssues
  • Loading branch information
dangeross authored and erdemyerebasmaz committed Mar 27, 2024
1 parent e8e4bba commit 0198402
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ object Constants {
"lnurl_pay_notification_channel_name"
const val LNURL_PAY_NOTIFICATION_FAILURE_TITLE =
"lnurl_pay_notification_failure_title"
const val LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE =
"lnurl_pay_notification_liquidity_failure_title"
const val LNURL_PAY_WORKGROUP_ID = "lnurl_pay"
const val LNURL_PAY_WORKGROUP_DESCRIPTION = "lnurl_pay_work_group_description"
const val LNURL_PAY_WORKGROUP_NAME = "lnurl_pay_work_group_name"
Expand Down Expand Up @@ -85,14 +87,16 @@ object Constants {
const val DEFAULT_LNURL_PAY_INFO_NOTIFICATION_TITLE =
"Retrieving Payment Information"
const val DEFAULT_LNURL_PAY_INVOICE_NOTIFICATION_TITLE =
"Fetching invoice"
"Fetching Invoice"
const val DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT =
"Pay with LNURL"
const val DEFAULT_LNURL_PAY_NOTIFICATION_CHANNEL_DESCRIPTION =
"Notifications for receiving payments when the application is in the background"
const val DEFAULT_LNURL_PAY_NOTIFICATION_CHANNEL_NAME = "Receiving Payments"
const val DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE =
"Receive Payment Failed"
const val DEFAULT_LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE =
"Fee Limit Too Low"
const val DEFAULT_LNURL_PAY_WORKGROUP_DESCRIPTION =
"Required to handle LNURL pay requests when the application is in the background"
const val DEFAULT_LNURL_PAY_WORKGROUP_NAME = "LNURL Payments"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ interface LnurlPayJob : Job {
}
}
}

class InvalidMinSendableException(message: String) : Exception(message)
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import breez_sdk.OpenChannelFeeRequest
import breez_sdk_notification.Constants.DEFAULT_LNURL_PAY_INFO_NOTIFICATION_TITLE
import breez_sdk_notification.Constants.DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT
import breez_sdk_notification.Constants.DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE
import breez_sdk_notification.Constants.DEFAULT_LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE
import breez_sdk_notification.Constants.LNURL_PAY_INFO_NOTIFICATION_TITLE
import breez_sdk_notification.Constants.LNURL_PAY_METADATA_PLAIN_TEXT
import breez_sdk_notification.Constants.LNURL_PAY_NOTIFICATION_FAILURE_TITLE
import breez_sdk_notification.Constants.LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE
import breez_sdk_notification.Constants.NOTIFICATION_CHANNEL_LNURL_PAY
import breez_sdk_notification.NotificationHelper.Companion.notifyChannel
import breez_sdk_notification.ResourceHelper.Companion.getString
Expand Down Expand Up @@ -53,8 +55,7 @@ class LnurlPayInfoJob(
try {
request = Json.decodeFromString(LnurlInfoRequest.serializer(), payload)
// Get the fee parameters offered by the LSP for opening a new channel
val ofp =
breezSDK.openChannelFee(OpenChannelFeeRequest(amountMsat = null)).feeParams
val ofp = breezSDK.openChannelFee(OpenChannelFeeRequest(amountMsat = null)).feeParams
// Calculate the maximum receivable amount within the fee limit (in millisatoshis)
val feeLimitMsat: ULong = config.channelFeeLimitMsat
val nodeInfo = breezSDK.nodeInfo()
Expand All @@ -77,21 +78,18 @@ class LnurlPayInfoJob(
val minSendable: ULong =
if (nodeInfo.inboundLiquidityMsats < 1000UL) ofp.minMsat else 1000UL
if (minSendable > maxSendable) {
throw Exception("Minimum sendable amount can't be greater than maximum sendable amount.")
throw InvalidMinSendableException("Minimum sendable amount can't be greater than maximum sendable amount.")
}
val plainTextMetadata = getString(
context,
LNURL_PAY_METADATA_PLAIN_TEXT,
DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT
context, LNURL_PAY_METADATA_PLAIN_TEXT, DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT
)
val response = LnurlPayInfoResponse(
request.callbackURL,
maxSendable,
minSendable,
"[[\"text/plain\",\"$plainTextMetadata\"]]",
"payRequest",
)
val response =
LnurlPayInfoResponse(
request.callbackURL,
maxSendable,
minSendable,
"[[\"text/plain\",\"$plainTextMetadata\"]]",
"payRequest",
)
val success = replyServer(Json.encodeToString(response), request.replyURL)
notifyChannel(
context,
Expand All @@ -112,8 +110,8 @@ class LnurlPayInfoJob(
NOTIFICATION_CHANNEL_LNURL_PAY,
getString(
context,
LNURL_PAY_NOTIFICATION_FAILURE_TITLE,
DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE
if (e is InvalidMinSendableException) LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE else LNURL_PAY_NOTIFICATION_FAILURE_TITLE,
if (e is InvalidMinSendableException) DEFAULT_LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE else DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ struct Constants {
static let LNURL_PAY_INVOICE_NOTIFICATION_TITLE = "lnurl_pay_invoice_notification_title"
static let LNURL_PAY_METADATA_PLAIN_TEXT = "lnurl_pay_metadata_plain_text"
static let LNURL_PAY_NOTIFICATION_FAILURE_TITLE = "lnurl_pay_notification_failure_title"
static let LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE = "lnurl_pay_notification_liquidity_failure_title"
static let PAYMENT_RECEIVED_NOTIFICATION_TITLE = "payment_received_notification_title"
static let PAYMENT_RECEIVED_NOTIFICATION_FAILURE_TITLE = "payment_received_notification_failure_title"
static let SWAP_TX_CONFIRMED_NOTIFICATION_TITLE = "swap_tx_confirmed_notification_title"
static let SWAP_TX_CONFIRMED_NOTIFICATION_FAILURE_TITLE = "swap_tx_confirmed_notification_failure_title"

// Resource Identifier Defaults
static let DEFAULT_LNURL_PAY_INFO_NOTIFICATION_TITLE = "Retrieving Payment Information"
static let DEFAULT_LNURL_PAY_INVOICE_NOTIFICATION_TITLE = "Fetching invoice"
static let DEFAULT_LNURL_PAY_INVOICE_NOTIFICATION_TITLE = "Fetching Invoice"
static let DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT = "Pay with LNURL"
static let DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE = "Receive Payment Failed"
static let DEFAULT_LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE = "Fee Limit Too Low"
static let DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_TITLE = "Received %d sats"
static let DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_FAILURE_TITLE = "Receive Payment Failed"
static let DEFAULT_SWAP_TX_CONFIRMED_NOTIFICATION_TITLE = "Swap Confirmed"
static let DEFAULT_SWAP_TX_CONFIRMED_NOTIFICATION_FAILURE_TITLE = "Redeem Swap Failed"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class LnurlPayTask : TaskProtocol {
var bestAttemptContent: UNMutableNotificationContent?
var logger: ServiceLogger
var config: ServiceConfig
var successNotifiationTitle: String
var successNotificationTitle: String
var failNotificationTitle: String

init(payload: String, logger: ServiceLogger, config: ServiceConfig, contentHandler: ((UNNotificationContent) -> Void)? = nil, bestAttemptContent: UNMutableNotificationContent? = nil, successNotificationTitle: String, failNotificationTitle: String) {
Expand All @@ -26,7 +26,7 @@ class LnurlPayTask : TaskProtocol {
self.bestAttemptContent = bestAttemptContent
self.logger = logger
self.config = config
self.successNotifiationTitle = successNotificationTitle;
self.successNotificationTitle = successNotificationTitle;
self.failNotificationTitle = failNotificationTitle;
}

Expand All @@ -50,7 +50,7 @@ class LnurlPayTask : TaskProtocol {
let statusCode = (response as! HTTPURLResponse).statusCode

if statusCode == 200 {
self.displayPushNotification(title: self.successNotifiationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY)
self.displayPushNotification(title: self.successNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY)
} else {
self.displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY)
return
Expand All @@ -59,7 +59,7 @@ class LnurlPayTask : TaskProtocol {
task.resume()
}

func fail(withError: String, replyURL: String) {
func fail(withError: String, replyURL: String, failNotificationTitle: String? = nil) {
if let serverReplyURL = URL(string: replyURL) {
var request = URLRequest(url: serverReplyURL)
request.httpMethod = "POST"
Expand All @@ -69,6 +69,7 @@ class LnurlPayTask : TaskProtocol {
}
task.resume()
}
self.displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY)
var title = failNotificationTitle != nil ? failNotificationTitle! : self.failNotificationTitle
self.displayPushNotification(title: title, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ class LnurlPayInfoTask : LnurlPayTask {
let maxSendable = max(nodeInfo.inboundLiquidityMsats, maxReceivableMsatFeeLimit)
// Get the minimum sendable amount (in millisatoshis), can not be less than 1 or more than maxSendable
let minSendable: UInt64 = nodeInfo.inboundLiquidityMsats < UInt64(1000) ? ofp.minMsat : UInt64(1000)
if(minSendable > maxSendable) {
if minSendable > maxSendable {
throw InvalidMinSendable.largerThanMaxSendable
}
replyServer(encodable: LnurlInfoResponse(callback: request!.callback_url, maxSendable: maxSendable, minSendable: minSendable, metadata: metadata, tag: "payRequest"),
replyURL: request!.reply_url)
} catch let e as InvalidMinSendable.largerThanMaxSendable {
self.logger.log(tag: TAG, line: "failed to process lnurl: \(e)", level: "ERROR")
let failNotificationTitle = ResourceHelper.shared.getString(key: Constants.LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE, fallback: Constants.DEFAULT_LNURL_PAY_NOTIFICATION_LIQUIDITY_FAILURE_TITLE)
fail(withError: e.localizedDescription, replyURL: request!.reply_url, failNotificationTitle: failNotificationTitle)
} catch let e {
self.logger.log(tag: TAG, line: "failed to process lnurl: \(e)", level: "ERROR")
fail(withError: e.localizedDescription, replyURL: request!.reply_url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ReceivePaymentTask : TaskProtocol {

func onShutdown() {
let successReceivedPayment = ResourceHelper.shared.getString(key: Constants.PAYMENT_RECEIVED_NOTIFICATION_TITLE, validateContains: "%d", fallback: Constants.DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_TITLE)
let failReceivedPayment = ResourceHelper.shared.getString(key: Constants.LNURL_PAY_NOTIFICATION_FAILURE_TITLE, fallback: Constants.DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE)
let failReceivedPayment = ResourceHelper.shared.getString(key: Constants.PAYMENT_RECEIVED_NOTIFICATION_FAILURE_TITLE, fallback: Constants.DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_FAILURE_TITLE)
let title = self.receivedPayment != nil ? String(format: successReceivedPayment, self.receivedPayment!.amountMsat/1000) : failReceivedPayment
self.displayPushNotification(title: title, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_PAYMENT_RECEIVED)
}
Expand Down

0 comments on commit 0198402

Please sign in to comment.