mirror of
https://github.com/aljazceru/breez-sdk-liquid.git
synced 2025-12-20 15:34:26 +01:00
166 lines
7.2 KiB
Swift
166 lines
7.2 KiB
Swift
import UserNotifications
|
|
import Foundation
|
|
|
|
struct SwapUpdatedRequest: Codable {
|
|
let id: String
|
|
let status: String
|
|
}
|
|
|
|
class SwapUpdatedTask : TaskProtocol {
|
|
fileprivate let TAG = "SwapUpdatedTask"
|
|
|
|
private let pollingInterval: TimeInterval = 5.0
|
|
|
|
internal var payload: String
|
|
internal var contentHandler: ((UNNotificationContent) -> Void)?
|
|
internal var bestAttemptContent: UNMutableNotificationContent?
|
|
internal var logger: ServiceLogger
|
|
internal var request: SwapUpdatedRequest? = nil
|
|
internal var notified: Bool = false
|
|
private var pollingTimer: Timer?
|
|
|
|
init(payload: String, logger: ServiceLogger, contentHandler: ((UNNotificationContent) -> Void)? = nil, bestAttemptContent: UNMutableNotificationContent? = nil) {
|
|
self.payload = payload
|
|
self.contentHandler = contentHandler
|
|
self.bestAttemptContent = bestAttemptContent
|
|
self.logger = logger
|
|
}
|
|
|
|
func start(liquidSDK: BindingLiquidSdk) throws {
|
|
do {
|
|
self.request = try JSONDecoder().decode(SwapUpdatedRequest.self, from: self.payload.data(using: .utf8)!)
|
|
} catch let e {
|
|
self.logger.log(tag: TAG, line: "Failed to decode payload: \(e)", level: "ERROR")
|
|
self.onShutdown()
|
|
throw e
|
|
}
|
|
|
|
startPolling(liquidSDK: liquidSDK)
|
|
}
|
|
|
|
func startPolling(liquidSDK: BindingLiquidSdk) {
|
|
pollingTimer = Timer.scheduledTimer(withTimeInterval: pollingInterval, repeats: true) { [weak self] _ in
|
|
guard let self = self else { return }
|
|
do {
|
|
guard let request = self.request else {
|
|
self.stopPolling(withError: NSError(domain: "SwapUpdatedTask", code: -1, userInfo: [NSLocalizedDescriptionKey: "Missing swap updated request"]))
|
|
return
|
|
}
|
|
|
|
if let payment = try liquidSDK.getPayment(req: .swapId(swapId: request.id)) {
|
|
switch payment.status {
|
|
case .complete:
|
|
onEvent(e: SdkEvent.paymentSucceeded(details: payment))
|
|
self.stopPolling()
|
|
case .waitingFeeAcceptance:
|
|
onEvent(e: SdkEvent.paymentWaitingFeeAcceptance(details: payment))
|
|
self.stopPolling()
|
|
case .pending:
|
|
if paymentClaimIsBroadcasted(details: payment.details) {
|
|
onEvent(e: SdkEvent.paymentWaitingConfirmation(details: payment))
|
|
self.stopPolling()
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
} catch {
|
|
self.stopPolling(withError: error)
|
|
}
|
|
}
|
|
|
|
pollingTimer?.fire()
|
|
}
|
|
|
|
private func stopPolling(withError error: Error? = nil) {
|
|
pollingTimer?.invalidate()
|
|
pollingTimer = nil
|
|
|
|
if let error = error {
|
|
logger.log(tag: TAG, line: "Polling stopped with error: \(error)", level: "ERROR")
|
|
onShutdown()
|
|
}
|
|
}
|
|
|
|
public func onEvent(e: SdkEvent) {
|
|
if let swapIdHash = self.request?.id {
|
|
switch e {
|
|
case .paymentWaitingConfirmation(details: let payment), .paymentSucceeded(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.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
|
|
}
|
|
}
|
|
}
|
|
|
|
func getSwapId(details: PaymentDetails?) -> String? {
|
|
if let details = details {
|
|
switch details {
|
|
case let .bitcoin(swapId, _, _, _, _, _, _, _, _):
|
|
return swapId
|
|
case let .lightning(swapId, _, _, _, _, _, _, _, _, _, _, _, _):
|
|
return swapId
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func paymentClaimIsBroadcasted(details: PaymentDetails) -> Bool {
|
|
switch details {
|
|
case let .bitcoin(_, _, _, _, _, _, claimTxId, _, _):
|
|
return claimTxId != nil
|
|
case let .lightning(_, _, _, _, _, _, _, _, _, _, claimTxId, _, _):
|
|
return claimTxId != nil
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func onShutdown() {
|
|
let notificationTitle = ResourceHelper.shared.getString(key: Constants.SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE, fallback: Constants.DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TITLE)
|
|
let notificationBody = ResourceHelper.shared.getString(key: Constants.SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT, fallback: Constants.DEFAULT_SWAP_CONFIRMED_NOTIFICATION_FAILURE_TEXT)
|
|
self.displayPushNotification(title: notificationTitle, body: notificationBody, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_DISMISSIBLE)
|
|
}
|
|
|
|
func notifySuccess(payment: Payment) {
|
|
if !self.notified {
|
|
self.logger.log(tag: TAG, line: "Payment \(payment.txId ?? "") processing successful", level: "INFO")
|
|
let received = payment.paymentType == PaymentType.receive
|
|
let notificationTitle = ResourceHelper.shared.getString(
|
|
key: received ? Constants.PAYMENT_RECEIVED_NOTIFICATION_TITLE : Constants.PAYMENT_SENT_NOTIFICATION_TITLE,
|
|
validateContains: "%d",
|
|
fallback: received ? Constants.DEFAULT_PAYMENT_RECEIVED_NOTIFICATION_TITLE: Constants.DEFAULT_PAYMENT_SENT_NOTIFICATION_TITLE)
|
|
self.notified = true
|
|
self.displayPushNotification(title: String(format: notificationTitle, payment.amountSat), logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_DISMISSIBLE)
|
|
}
|
|
}
|
|
|
|
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_DISMISSIBLE)
|
|
}
|
|
}
|
|
}
|