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

Show notification if payment requires fee acceptance #634

Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ object Constants {
"payment_sent_notification_text"
const val PAYMENT_SENT_NOTIFICATION_TITLE =
"payment_sent_notification_title"
const val PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE =
"payment_waiting_fee_acceptance_notification_title"
const val PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT =
"payment_waiting_fee_acceptance_text"
const val SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT =
"swap_confirmed_notification_failure_text"
const val SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE =
Expand Down Expand Up @@ -102,6 +106,10 @@ object Constants {
"Sent %d sats"
const val DEFAULT_PAYMENT_SENT_NOTIFICATION_TITLE =
"Payment Sent"
const val DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE =
"Payment requires fee acceptance"
const val DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT =
"Tap to review updated fees"
const val DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT =
"Tap to complete payment"
const val DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_RECEIVED_NOTIFICA
import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_TITLE
import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_SENT_NOTIFICATION_TEXT
import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_SENT_NOTIFICATION_TITLE
import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT
import breez_sdk_liquid_notification.Constants.DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE
import breez_sdk_liquid_notification.Constants.DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT
import breez_sdk_liquid_notification.Constants.DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE
import breez_sdk_liquid_notification.Constants.NOTIFICATION_CHANNEL_SWAP_UPDATED
import breez_sdk_liquid_notification.Constants.PAYMENT_RECEIVED_NOTIFICATION_TEXT
import breez_sdk_liquid_notification.Constants.PAYMENT_RECEIVED_NOTIFICATION_TITLE
import breez_sdk_liquid_notification.Constants.PAYMENT_SENT_NOTIFICATION_TEXT
import breez_sdk_liquid_notification.Constants.PAYMENT_SENT_NOTIFICATION_TITLE
import breez_sdk_liquid_notification.Constants.PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT
import breez_sdk_liquid_notification.Constants.PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE
import breez_sdk_liquid_notification.Constants.SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT
import breez_sdk_liquid_notification.Constants.SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE
import breez_sdk_liquid_notification.NotificationHelper.Companion.notifyChannel
Expand Down Expand Up @@ -57,8 +61,9 @@ class SwapUpdatedJob(

override fun onEvent(e: SdkEvent) {
when (e) {
is SdkEvent.PaymentWaitingConfirmation -> handlePaymentEvent(e.details)
is SdkEvent.PaymentSucceeded -> handlePaymentEvent(e.details)
is SdkEvent.PaymentWaitingConfirmation -> handlePaymentSuccess(e.details)
is SdkEvent.PaymentSucceeded -> handlePaymentSuccess(e.details)
is SdkEvent.PaymentWaitingFeeAcceptance -> handlePaymentWaitingFeeAcceptance(e.details)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment here is not related to this PR but I think we might miss the notification if the app keeps working in the background and we have two sdk instances as one instance will emit it and the notifications job instance will miss it?
Perhaps we should record the state when we get the notification and poll for changes in addition to waiting for events?
@dangeross what do you think?
Even if this is indeed something we need to fix I suggest not to handle that as part of this PR as it was introduced before.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the swap is already WaitingFeeAcceptance I guess the swap isn't tracked (last swap status received in loop) when the notification SDK instance is started? If so I think you're right, we should fetch the payment by the hashed swap id, then check it's state and/or wait for events.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roeierez I created an issue to track this. I haven't seen this in practice, but I usually stop the app when testing the notification, so I wouldn't notice it.


else -> {
logger.log(TAG, "Received event: ${e}", "TRACE")
Expand All @@ -76,12 +81,16 @@ class SwapUpdatedJob(
.fold(StringBuilder()) { sb, it -> sb.append("%02x".format(it)) }
.toString()

private fun handlePaymentEvent(payment: Payment) {
val swapId = when (val details = payment.details) {
private fun getSwapId(details: PaymentDetails?): String? {
return when (details) {
is PaymentDetails.Bitcoin -> details.swapId
is PaymentDetails.Lightning -> details.swapId
else -> null
}
}

private fun handlePaymentSuccess(payment: Payment) {
val swapId = getSwapId(payment.details)

swapId?.let {
if (this.swapIdHash == hashId(it)) {
Expand All @@ -95,6 +104,21 @@ class SwapUpdatedJob(
}
}

private fun handlePaymentWaitingFeeAcceptance(payment: Payment) {
val swapId = getSwapId(payment.details)

swapId?.let {
if (this.swapIdHash == hashId(it)) {
logger.log(
TAG,
"Payment waiting fee acceptance: ${this.swapIdHash}",
"TRACE"
)
notifyPaymentWaitingFeeAcceptance(payment)
}
}
}

private fun notifySuccess(payment: Payment) {
if (!this.notified) {
logger.log(TAG, "Payment ${payment.txId} processing successful", "INFO")
Expand All @@ -121,6 +145,28 @@ class SwapUpdatedJob(
}
}

private fun notifyPaymentWaitingFeeAcceptance(payment: Payment) {
if (!this.notified) {
logger.log(TAG, "Payment with swap ID ${getSwapId(payment.details)} requires fee acceptance", "INFO")
notifyChannel(
context,
NOTIFICATION_CHANNEL_SWAP_UPDATED,
getString(
context,
PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE,
DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE
),
getString(
context,
PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT,
DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT
)
)
this.notified = true
fgService.onFinished(this)
}
}

private fun notifyFailure() {
this.swapIdHash?.let { swapIdHash ->
logger.log(TAG, "Swap $swapIdHash processing failed", "INFO")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct Constants {
static let LNURL_PAY_NOTIFICATION_FAILURE_TITLE = "lnurl_pay_notification_failure_title"
static let PAYMENT_RECEIVED_NOTIFICATION_TITLE = "payment_received_notification_title"
static let PAYMENT_SENT_NOTIFICATION_TITLE = "payment_sent_notification_title"
static let PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE = "payment_waiting_fee_acceptance_notification_title"
static let PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT = "payment_waiting_fee_acceptance_text"
static let SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT = "swap_confirmed_notification_failure_text"
static let SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE = "swap_confirmed_notification_failure_title"

Expand All @@ -30,6 +32,8 @@ struct Constants {
static let DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE = "Receive Payment Failed"
static let DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_TITLE = "Received %d sats"
static let DEFAULT_PAYMENT_SENT_NOTIFICATION_TITLE = "Sent %d sats"
static let DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE = "Payment requires fee acceptance"
static let DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT = "Tap to review updated fees"
static let DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT = "Tap to complete payment"
static let DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE = "Payment Pending"
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ class SwapUpdatedTask : TaskProtocol {
self.notifySuccess(payment: payment)
}
break
case .paymentWaitingFeeAcceptance(details: let payment):
let swapId = self.getSwapId(details: payment.details)
if swapIdHash == swapId?.sha256() {
self.logger.log(tag: TAG, line: "Received payment event: \(swapIdHash) \(payment.status)", level: "INFO")
self.notifyPaymentWaitingFeeAcceptance(payment: payment)
}
break
default:
break
}
Expand Down Expand Up @@ -81,4 +88,18 @@ class SwapUpdatedTask : TaskProtocol {
self.displayPushNotification(title: String(format: notificationTitle, payment.amountSat), logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_SWAP_UPDATED)
}
}

func notifyPaymentWaitingFeeAcceptance(payment: Payment) {
if !self.notified {
self.logger.log(tag: TAG, line: "Payment \(self.getSwapId(details: payment.details) ?? "") requires fee acceptance", level: "INFO")
let notificationTitle = ResourceHelper.shared.getString(
key: Constants.PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE,
fallback: Constants.DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TITLE)
let notificationBody = ResourceHelper.shared.getString(
key: Constants.PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT,
fallback: Constants.DEFAULT_PAYMENT_WAITING_FEE_ACCEPTANCE_TEXT)
self.notified = true
self.displayPushNotification(title: notificationTitle, body: notificationBody, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_SWAP_UPDATED)
}
}
}
Loading