-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update Breez SDK Flutter package to version v0.4.0-rc5
- Loading branch information
github-actions
committed
Apr 17, 2024
1 parent
8762a59
commit 6fc4037
Showing
15 changed files
with
667 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
group 'com.breez.breez_sdk' | ||
version '0.4.0-rc2' | ||
version '0.4.0-rc5' | ||
|
||
buildscript { | ||
ext.kotlin_version = '1.8.20' | ||
|
49 changes: 49 additions & 0 deletions
49
ios/bindings-swift/Sources/BreezSDK/BreezSDKConnector.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import Foundation | ||
import os.log | ||
|
||
#if DEBUG && true | ||
fileprivate var logger = OSLog( | ||
subsystem: Bundle.main.bundleIdentifier!, | ||
category: "BreezSDKConnector" | ||
) | ||
#else | ||
fileprivate var logger = OSLog.disabled | ||
#endif | ||
|
||
class BreezSDKConnector { | ||
private static var breezSDK: BlockingBreezServices? = nil | ||
fileprivate static var queue = DispatchQueue(label: "BreezSDKConnector") | ||
fileprivate static var sdkListener: EventListener? = nil | ||
|
||
static func register(connectRequest: ConnectRequest, listener: EventListener) throws -> BlockingBreezServices? { | ||
try BreezSDKConnector.queue.sync { [] in | ||
BreezSDKConnector.sdkListener = listener | ||
if BreezSDKConnector.breezSDK == nil { | ||
BreezSDKConnector.breezSDK = try BreezSDKConnector.connectSDK(connectRequest: connectRequest) | ||
} | ||
return BreezSDKConnector.breezSDK | ||
} | ||
} | ||
|
||
static func unregister() { | ||
BreezSDKConnector.queue.sync { [] in | ||
BreezSDKConnector.sdkListener = nil | ||
} | ||
} | ||
|
||
static func connectSDK(connectRequest: ConnectRequest) throws -> BlockingBreezServices? { | ||
// Connect to the Breez SDK make it ready for use | ||
os_log("Connecting to Breez SDK", log: logger, type: .debug) | ||
let breezSDK = try connect(req: connectRequest, listener: BreezSDKEventListener()) | ||
os_log("Connected to Breez SDK", log: logger, type: .debug) | ||
return breezSDK | ||
} | ||
} | ||
|
||
class BreezSDKEventListener: EventListener { | ||
func onEvent(e: BreezEvent) { | ||
BreezSDKConnector.queue.async { [] in | ||
BreezSDKConnector.sdkListener?.onEvent(e: e) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Foundation | ||
|
||
struct Constants { | ||
// Notification Threads | ||
static let NOTIFICATION_THREAD_LNURL_PAY = "LNURL_PAY" | ||
static let NOTIFICATION_THREAD_PAYMENT_RECEIVED = "PAYMENT_RECEIVED" | ||
static let NOTIFICATION_THREAD_SWAP_TX_CONFIRMED = "SWAP_TX_CONFIRMED" | ||
|
||
// Message Data | ||
static let MESSAGE_DATA_TYPE = "notification_type" | ||
static let MESSAGE_DATA_PAYLOAD = "notification_payload" | ||
|
||
static let MESSAGE_TYPE_ADDRESS_TXS_CONFIRMED = "address_txs_confirmed" | ||
static let MESSAGE_TYPE_LNURL_PAY_INFO = "lnurlpay_info" | ||
static let MESSAGE_TYPE_LNURL_PAY_INVOICE = "lnurlpay_invoice" | ||
static let MESSAGE_TYPE_PAYMENT_RECEIVED = "payment_received" | ||
|
||
// Resource Identifiers | ||
static let LNURL_PAY_INFO_NOTIFICATION_TITLE = "lnurl_pay_info_notification_title" | ||
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_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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import Foundation | ||
|
||
public class ResourceHelper { | ||
public static let shared = ResourceHelper() | ||
|
||
private init() {/* must use shared instance */} | ||
|
||
public func getString(key: String, fallback: String) -> String { | ||
return getString(key: key, validateContains: nil, fallback: fallback) | ||
} | ||
|
||
public func getString(key: String, validateContains: String?, fallback: String) -> String { | ||
if let str = Bundle.main.object(forInfoDictionaryKey: key) as? String { | ||
if validateContains == nil || str.contains(validateContains!) { | ||
return str | ||
} | ||
} | ||
return fallback | ||
}} |
109 changes: 109 additions & 0 deletions
109
ios/bindings-swift/Sources/BreezSDK/SDKNotificationService.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import UserNotifications | ||
import os.log | ||
|
||
open class SDKNotificationService: UNNotificationServiceExtension { | ||
fileprivate let TAG = "SDKNotificationService" | ||
|
||
var breezSDK: BlockingBreezServices? | ||
var contentHandler: ((UNNotificationContent) -> Void)? | ||
var bestAttemptContent: UNMutableNotificationContent? | ||
var currentTask: TaskProtocol? | ||
var logger: ServiceLogger = ServiceLogger(logStream: nil) | ||
var config: ServiceConfig = ServiceConfig.default | ||
|
||
override init() { } | ||
|
||
override open func didReceive( | ||
_ request: UNNotificationRequest, | ||
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void | ||
) { | ||
self.logger.log(tag: TAG, line: "Notification received", level: "INFO") | ||
self.contentHandler = contentHandler | ||
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) | ||
|
||
if let config = self.getServiceConfig() { | ||
setConfig(config: config) | ||
} | ||
|
||
guard let connectRequest = self.getConnectRequest() else { | ||
if let content = bestAttemptContent { | ||
contentHandler(content) | ||
} | ||
return | ||
} | ||
|
||
if let currentTask = self.getTaskFromNotification() { | ||
self.currentTask = currentTask | ||
|
||
DispatchQueue.main.async { [self] in | ||
do { | ||
logger.log(tag: TAG, line: "Breez SDK is not connected, connecting...", level: "INFO") | ||
breezSDK = try BreezSDKConnector.register(connectRequest: connectRequest, listener: currentTask) | ||
logger.log(tag: TAG, line: "Breez SDK connected successfully", level: "INFO") | ||
try currentTask.start(breezSDK: breezSDK!) | ||
} catch { | ||
logger.log(tag: TAG, line: "Breez SDK connection failed \(error)", level: "ERROR") | ||
shutdown() | ||
} | ||
} | ||
} | ||
} | ||
|
||
open func getConnectRequest() -> ConnectRequest? { | ||
return nil | ||
} | ||
|
||
open func getServiceConfig() -> ServiceConfig? { | ||
return nil | ||
} | ||
|
||
open func getTaskFromNotification() -> TaskProtocol? { | ||
guard let content = bestAttemptContent else { return nil } | ||
guard let notificationType = content.userInfo[Constants.MESSAGE_DATA_TYPE] as? String else { return nil } | ||
self.logger.log(tag: TAG, line: "Notification payload: \(content.userInfo)", level: "INFO") | ||
self.logger.log(tag: TAG, line: "Notification type: \(notificationType)", level: "INFO") | ||
|
||
guard let payload = content.userInfo[Constants.MESSAGE_DATA_PAYLOAD] as? String else { | ||
contentHandler!(content) | ||
return nil | ||
} | ||
|
||
self.logger.log(tag: TAG, line: "\(notificationType) data string: \(payload)", level: "INFO") | ||
switch(notificationType) { | ||
case Constants.MESSAGE_TYPE_ADDRESS_TXS_CONFIRMED: | ||
return RedeemSwapTask(payload: payload, logger: self.logger, contentHandler: contentHandler, bestAttemptContent: bestAttemptContent) | ||
case Constants.MESSAGE_TYPE_LNURL_PAY_INFO: | ||
return LnurlPayInfoTask(payload: payload, logger: self.logger, config: self.config, contentHandler: contentHandler, bestAttemptContent: bestAttemptContent) | ||
case Constants.MESSAGE_TYPE_LNURL_PAY_INVOICE: | ||
return LnurlPayInvoiceTask(payload: payload, logger: self.logger, config: self.config, contentHandler: contentHandler, bestAttemptContent: bestAttemptContent) | ||
case Constants.MESSAGE_TYPE_PAYMENT_RECEIVED: | ||
return ReceivePaymentTask(payload: payload, logger: self.logger, contentHandler: contentHandler, bestAttemptContent: bestAttemptContent) | ||
default: | ||
return nil | ||
} | ||
} | ||
|
||
override open func serviceExtensionTimeWillExpire() { | ||
self.logger.log(tag: TAG, line: "serviceExtensionTimeWillExpire()", level: "INFO") | ||
|
||
// iOS calls this function just before the extension will be terminated by the system. | ||
// Use this as an opportunity to deliver your "best attempt" at modified content, | ||
// otherwise the original push payload will be used. | ||
self.shutdown() | ||
} | ||
|
||
private func shutdown() -> Void { | ||
self.logger.log(tag: TAG, line: "shutting down...", level: "INFO") | ||
BreezSDKConnector.unregister() | ||
self.logger.log(tag: TAG, line: "task unregistered", level: "INFO") | ||
self.currentTask?.onShutdown() | ||
} | ||
|
||
func setLogger(logger: LogStream) { | ||
self.logger = ServiceLogger(logStream: logger) | ||
} | ||
|
||
private func setConfig(config: ServiceConfig) { | ||
self.config = config | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
public struct ServiceConfig { | ||
// MARK: - Constants | ||
public struct Constants { | ||
/// Channel setup fee limit (in msats) for the default instance of ServiceConfig | ||
public static let defaultChannelFeeLimitMsat = UInt64(0) | ||
} | ||
|
||
// MARK: - Default instance | ||
/// The default ServiceConfig object | ||
public static let `default`: ServiceConfig = ServiceConfig(channelFeeLimitMsat: ServiceConfig.Constants.defaultChannelFeeLimitMsat) | ||
|
||
// MARK: - Properties | ||
/// Channel setup fee limit (in msats) | ||
public var channelFeeLimitMsat: UInt64! = UInt64(0) | ||
|
||
// MARK: - Life Cycle | ||
public init(channelFeeLimitMsat: UInt64) { | ||
self.channelFeeLimitMsat = channelFeeLimitMsat | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Foundation | ||
import os.log | ||
|
||
#if DEBUG && true | ||
fileprivate var logger = OSLog( | ||
subsystem: Bundle.main.bundleIdentifier!, | ||
category: "ServiceLogger" | ||
) | ||
#else | ||
fileprivate var logger = OSLog.disabled | ||
#endif | ||
|
||
class ServiceLogger { | ||
var logStream: LogStream? | ||
|
||
init(logStream: LogStream?) { | ||
self.logStream = logStream | ||
} | ||
|
||
func log(tag: String, line: String, level: String) { | ||
if let logger = logStream { | ||
logger.log(l: LogEntry(line: line, level: level)) | ||
} else { | ||
switch(level) { | ||
case "ERROR": | ||
os_log("[%{public}@] %{public}@", log: logger, type: .error, tag, line) | ||
break | ||
case "INFO", "WARN": | ||
os_log("[%{public}@] %{public}@", log: logger, type: .info, tag, line) | ||
break | ||
case "TRACE": | ||
os_log("[%{public}@] %{public}@", log: logger, type: .debug, tag, line) | ||
break | ||
default: | ||
os_log("[%{public}@] %{public}@", log: logger, type: .default, tag, line) | ||
return | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import UserNotifications | ||
import Foundation | ||
|
||
struct LnurlErrorResponse: Decodable, Encodable { | ||
let status: String | ||
let reason: String | ||
|
||
init(status: String, reason: String) { | ||
self.status = status | ||
self.reason = reason | ||
} | ||
} | ||
|
||
class LnurlPayTask : TaskProtocol { | ||
var payload: String | ||
var contentHandler: ((UNNotificationContent) -> Void)? | ||
var bestAttemptContent: UNMutableNotificationContent? | ||
var logger: ServiceLogger | ||
var config: ServiceConfig | ||
var successNotificationTitle: String | ||
var failNotificationTitle: String | ||
|
||
init(payload: String, logger: ServiceLogger, config: ServiceConfig, contentHandler: ((UNNotificationContent) -> Void)? = nil, bestAttemptContent: UNMutableNotificationContent? = nil, successNotificationTitle: String, failNotificationTitle: String) { | ||
self.payload = payload | ||
self.contentHandler = contentHandler | ||
self.bestAttemptContent = bestAttemptContent | ||
self.logger = logger | ||
self.config = config | ||
self.successNotificationTitle = successNotificationTitle; | ||
self.failNotificationTitle = failNotificationTitle; | ||
} | ||
|
||
public func onEvent(e: BreezEvent) {} | ||
|
||
func start(breezSDK: BlockingBreezServices) throws {} | ||
|
||
func onShutdown() { | ||
displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY) | ||
} | ||
|
||
func replyServer(encodable: Encodable, replyURL: String) { | ||
guard let serverReplyURL = URL(string: replyURL) else { | ||
self.displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY) | ||
return | ||
} | ||
var request = URLRequest(url: serverReplyURL) | ||
request.httpMethod = "POST" | ||
request.httpBody = try! JSONEncoder().encode(encodable) | ||
let task = URLSession.shared.dataTask(with: request) { data, response, error in | ||
let statusCode = (response as! HTTPURLResponse).statusCode | ||
|
||
if statusCode == 200 { | ||
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 | ||
} | ||
} | ||
task.resume() | ||
} | ||
|
||
func fail(withError: String, replyURL: String, failNotificationTitle: String? = nil) { | ||
if let serverReplyURL = URL(string: replyURL) { | ||
var request = URLRequest(url: serverReplyURL) | ||
request.httpMethod = "POST" | ||
request.httpBody = try! JSONEncoder().encode(LnurlErrorResponse(status: "ERROR", reason: withError)) | ||
let task = URLSession.shared.dataTask(with: request) { data, response, error in | ||
let _ = (response as! HTTPURLResponse).statusCode | ||
} | ||
task.resume() | ||
} | ||
var title = failNotificationTitle != nil ? failNotificationTitle! : self.failNotificationTitle | ||
self.displayPushNotification(title: title, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_LNURL_PAY) | ||
} | ||
} |
Oops, something went wrong.