diff --git a/snippets/csharp/GettingStarted.cs b/snippets/csharp/GettingStarted.cs index 76ee4708..d9a8b0ae 100644 --- a/snippets/csharp/GettingStarted.cs +++ b/snippets/csharp/GettingStarted.cs @@ -76,4 +76,27 @@ public void FetchNodeInfo(BlockingBreezServices sdk) } // ANCHOR_END: fetch-balance } + + // ANCHOR: logging + public void GettingStartedLogging() + { + try + { + BreezSdkMethods.SetLogStream(new SdkLogStream()); + } + catch (Exception) + { + // Handle error + } + } + + class SdkLogStream : LogStream + { + public void Log(LogEntry l) + { + Console.WriteLine($"Received Log [{l.level}]: {l.line}"); + } + } + // ANCHOR_END: logging + } diff --git a/snippets/csharp/Production.cs b/snippets/csharp/Production.cs index 63e390a3..853c6ef7 100644 --- a/snippets/csharp/Production.cs +++ b/snippets/csharp/Production.cs @@ -4,7 +4,8 @@ public class ProductionSnippets { public NodeConfig ProductionNodeConfig() { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config var deviceKey = new List(); var deviceCert = new List(); var greenlightCredentials = new GreenlightCredentials(deviceKey, deviceCert); diff --git a/snippets/dart_snippets/lib/getting_started.dart b/snippets/dart_snippets/lib/getting_started.dart index d19a566f..f98f0d8a 100644 --- a/snippets/dart_snippets/lib/getting_started.dart +++ b/snippets/dart_snippets/lib/getting_started.dart @@ -63,3 +63,13 @@ Future fetchBalance(String lspId) async { } // ANCHOR_END: fetch-balance } + +// ANCHOR: logging +void onLogEntry(log) { + print("Received log ${log.level}]: ${log.line}"); +} + +void logging(BreezSDK breezSDK) { + breezSDK.logStream.listen(onLogEntry); +} +// ANCHOR_END: logging diff --git a/snippets/dart_snippets/lib/production.dart b/snippets/dart_snippets/lib/production.dart index c2aea4e2..9e716ccc 100644 --- a/snippets/dart_snippets/lib/production.dart +++ b/snippets/dart_snippets/lib/production.dart @@ -4,7 +4,8 @@ import 'package:breez_sdk/bridge_generated.dart'; NodeConfig productionNodeConfig() { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config Uint8List deviceKey = Uint8List(0); Uint8List deviceCert = Uint8List(0); GreenlightCredentials greenlightCredentials = GreenlightCredentials( diff --git a/snippets/go/getting_started.go b/snippets/go/getting_started.go index 395ac9d4..017c51d4 100644 --- a/snippets/go/getting_started.go +++ b/snippets/go/getting_started.go @@ -71,3 +71,19 @@ func FetchBalance() { } // ANCHOR_END: fetch-balance } + +// ANCHOR: logging +type SdkLogStream struct{} + +func (SdkLogStream) Log(l breez_sdk.LogEntry) { + log.Printf("Received log [%v]: %v", l.Level, l.Line) +} + +func GettingStartedLogging() { + err := breez_sdk.SetLogStream(SdkLogStream{}) + if err != nil { + log.Fatalf("SetLogStream failed: %#v", err) + } +} + +// ANCHOR_END: logging diff --git a/snippets/go/production.go b/snippets/go/production.go index afc7d6eb..f73a7c95 100644 --- a/snippets/go/production.go +++ b/snippets/go/production.go @@ -6,7 +6,8 @@ import ( func ProductionNodeConfig() breez_sdk.NodeConfig { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config deviceKey := []uint8{} deviceCert := []uint8{} greenlightCredentials := breez_sdk.GreenlightCredentials{ diff --git a/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt b/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt index b01adf65..5d0faf10 100644 --- a/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt +++ b/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt @@ -60,4 +60,20 @@ class GettingStarted { } // ANCHOR_END: fetch-balance } + + fun logging() { + // ANCHOR: logging + class SDKLogStream : LogStream { + override fun log(l: LogEntry) { + // Log.v("SDKListener", "Received log [${l.level}]: ${l.line}") + } + } + + try { + setLogStream(SDKLogStream()) + } catch (e: Exception) { + // handle error + } + // ANCHOR_END: logging + } } \ No newline at end of file diff --git a/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Production.kt b/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Production.kt index 4fbcb2a7..761df2dd 100644 --- a/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Production.kt +++ b/snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/Production.kt @@ -4,7 +4,8 @@ import breez_sdk.* class Production { fun productionNodeConfig(): NodeConfig { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config val deviceKey = emptyList() val deviceCert = emptyList() val greenlightCredentials = GreenlightCredentials(deviceKey, deviceCert) diff --git a/snippets/python/src/getting_started.py b/snippets/python/src/getting_started.py index 22c2e682..a57b7886 100644 --- a/snippets/python/src/getting_started.py +++ b/snippets/python/src/getting_started.py @@ -56,4 +56,15 @@ def getting_started_node_info(sdk_services): logging.error(error) raise +# ANCHOR: logging +class SDKLogStream(breez_sdk.LogStream): + def log(self, l): + print("Received log [", l.level, "]: ", l.line) +def logging(): + try: + breez_sdk.set_log_stream(SDKLogStream()) + except Exception as error: + print(error) + raise +# ANCHOR_END: logging diff --git a/snippets/python/src/production.py b/snippets/python/src/production.py index 3603b5af..c796eb32 100644 --- a/snippets/python/src/production.py +++ b/snippets/python/src/production.py @@ -2,7 +2,8 @@ def production_node_config(): # ANCHOR: moving-to-production - # Read your Greenlight credentials from secure storage + # Read in your Greenlight credentials from the file + # system, environment variable or build config deviceKey = [] deviceCert = [] greenlightCredentials = breez_sdk.GreenlightCredentials(deviceKey, deviceCert) diff --git a/snippets/react-native/getting_started.ts b/snippets/react-native/getting_started.ts index 97f2d137..11435ed9 100644 --- a/snippets/react-native/getting_started.ts +++ b/snippets/react-native/getting_started.ts @@ -8,7 +8,9 @@ import { mnemonicToSeed, type NodeConfig, NodeConfigVariant, - nodeInfo + nodeInfo, + type LogEntry, + setLogStream } from '@breeztech/react-native-breez-sdk' const exampleGettingStarted = async () => { @@ -36,6 +38,13 @@ const exampleGettingStarted = async () => { nodeConfig ) + // By default in React Native the workingDir is set to: + // `//breezSdk` + // You can change this to another writable directory or a + // subdirectory of the workingDir if managing multiple nodes. + console.log(`Working directory: ${config.workingDir}`) + // config.workingDir = "path to writable directory" + // Connect to the Breez SDK make it ready for use const connectRequest: ConnectRequest = { config, seed } await connect(connectRequest, onBreezEvent) @@ -71,3 +80,13 @@ const exampleFetchNodeInfo = async () => { } // ANCHOR_END: fetch-balance } + +const exampleLogging = async () => { + // ANCHOR: logging + const onLogEntry = (l: LogEntry) => { + console.log(`Received log [${l.level}]: ${l.line}`) + } + + const subscription = await setLogStream(onLogEntry) + // ANCHOR_END: logging +} diff --git a/snippets/react-native/production.ts b/snippets/react-native/production.ts index 57795513..92d04f79 100644 --- a/snippets/react-native/production.ts +++ b/snippets/react-native/production.ts @@ -6,7 +6,8 @@ import { const productionNodeConfig = (): NodeConfig => { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config const deviceKey: number[] = [] const deviceCert: number[] = [] const greenlightCredentials: GreenlightCredentials = { diff --git a/snippets/rust/src/getting_started.rs b/snippets/rust/src/getting_started.rs index 5f82b515..d0538fff 100644 --- a/snippets/rust/src/getting_started.rs +++ b/snippets/rust/src/getting_started.rs @@ -1,7 +1,9 @@ +use std::{fs, path::PathBuf}; +use std::sync::Arc; + use anyhow::Result; use bip39::{Language, Mnemonic}; use breez_sdk_core::*; -use std::sync::Arc; use crate::AppEventListener; @@ -60,3 +62,14 @@ async fn getting_started_node_info(sdk: Arc) -> Result<()> { Ok(()) } + +async fn getting_started_logging(data_dir: String) -> Result<()> { + // ANCHOR: logging + let data_dir_path = PathBuf::from(&data_dir); + fs::create_dir_all(data_dir_path)?; + + BreezServices::init_logging(&data_dir, None)?; + // ANCHOR_END: logging + + Ok(()) +} diff --git a/snippets/rust/src/production.rs b/snippets/rust/src/production.rs index 85ae4a04..3a09329a 100644 --- a/snippets/rust/src/production.rs +++ b/snippets/rust/src/production.rs @@ -3,7 +3,8 @@ use breez_sdk_core::*; fn production_node_config() -> Result { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config let device_key: Vec = vec![]; let device_cert: Vec = vec![]; let greenlight_credentials = GreenlightCredentials { diff --git a/snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift b/snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift index b20e8357..4ce19016 100644 --- a/snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift +++ b/snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift @@ -57,3 +57,15 @@ func gettingStartedNodeInfo(sdk: BlockingBreezServices) { } // ANCHOR_END: fetch-balance } + +// ANCHOR: logging +class SDKLogStream: LogStream { + func log(l: LogEntry) { + print("Received log [", l.level, "]: ", l.line) + } +} + +func logging() throws { + try? setLogStream(logStream: SDKLogStream()) +} +// ANCHOR_END: logging diff --git a/snippets/swift/BreezSDKExamples/Sources/Production.swift b/snippets/swift/BreezSDKExamples/Sources/Production.swift index 3759b5b8..8e943a9a 100644 --- a/snippets/swift/BreezSDKExamples/Sources/Production.swift +++ b/snippets/swift/BreezSDKExamples/Sources/Production.swift @@ -9,7 +9,8 @@ import BreezSDK func productionNodeConfig() -> NodeConfig { // ANCHOR: moving-to-production - // Read your Greenlight credentials from secure storage + // Read in your Greenlight credentials from the file + // system, environment variable or build config let deviceKey = [UInt8]() let deviceCert = [UInt8]() let greenlightCredentials = GreenlightCredentials(deviceKey: deviceKey, deviceCert: deviceCert) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 36cf640e..4d7ac5d6 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -3,7 +3,11 @@ # API Overview - [Getting Started](guide/getting_started.md) -- [Installing](guide/install.md) + - [Installing the Breez SDK](guide/install.md) + - [Troubleshooting Android](guide/android_troubleshooting.md) + - [Connecting to a node](guide/connecting.md) + - [Getting the node state](guide/node_state.md) + - [Adding logging](guide/logging.md) - [Paying in Lightning](guide/payments.md) - [Receiving payments](guide/receive_payment.md) - [Sending payments](guide/send_payment.md) @@ -49,6 +53,7 @@ - [Adding logging](notifications/logging.md) - [Configuring the plugin](notifications/service_configuration.md) - [Changing default strings](notifications/changing_strings.md) +- [Customising push messages](notifications/custom_messages.md) - [Handling custom notifications](notifications/custom_notifications.md) diff --git a/src/guide/android_troubleshooting.md b/src/guide/android_troubleshooting.md new file mode 100644 index 00000000..dd807082 --- /dev/null +++ b/src/guide/android_troubleshooting.md @@ -0,0 +1,78 @@ +# Troubleshooting Android + +After installing Breez SDK into your application you might come across issues compiling on Android platforms because Breez SDK's Notification Plugin: +- uses `kotlinx-serialization` dependency, +- and it relies on JNA library. + +If you do, there are several steps you can take to compile and build properly, even if your application is not using the Notification Plugin feature. + +## kotlinx-serialization + +Starting with this 1.8.20 release, the Kotlin K2 compiler has a preview version of the serialization plugin. It's recommended for users to upgrade their Kotlin version to at least 1.8.20 or [set up the serialization plugin](https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#setup) on their projects explicitly with older versions. + +## JNA library + +JNA relies on specific class and method names to load native libraries and access native code. If these names are obfuscated or removed, it can cause runtime errors and failures in native library loading. + +The JNA library code obfuscation issue may not be apparent until your application is compiled on `release` mode with maximum optimization and minimal footprint size, that will be used when deploying and publishing an application. + +To ensure proper functionality, a Proguard rules needs to be added to explicitly tell R8 compiler to keep certain parts of the JNA library. Here is an example of Proguard rules: +```pro +-dontwarn dalvik.system.VMStack +-dontwarn java.lang.** +-dontwarn javax.naming.** +-dontwarn sun.reflect.Reflection + +# JNA +-keep class com.sun.jna.** { *; } +-keep class * implements com.sun.jna.** { *; } + +# Other +-dontoptimize +``` + +These rules ensure that the JNA library's core components are not obfuscated, allowing the library to function correctly. See [Shrink, obfuscate, and optimize your app](https://developer.android.com/build/shrink-code) for more information on how and where to add Proguard rules on your app. + +## Inconsistent JVM-target compatibility + +It could be that compilation tasks for Java and Kotlin are using different JVM targets, in which case you need to set the [JVM toolchain](https://kotl.in/gradle/jvm/toolchain). In your application's `build.gradle` file in the `app` directory set the Java and Kotlin JVM targets consistently. +``` +kotlin { + jvmToolchain(17) +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' + } +} +``` + +## Java heap space + +``` +> Could not resolve all files for configuration + > Failed to transform react-android-0.72.10-debug.aar (com.facebook.react:react-android:0.72.10) + to match attributes {artifactType=android-symbol-with-package-name, + com.android.build.api.attributes.BuildTypeAttr=debug, org.gradle.category=library, + org.gradle.dependency.bundling=external, or g.gradle.libraryelements=aar, org.gradle.status=release, + org.gradle.usage=java-api}. + > Java heap error +``` + +If you get a `Java heap space` error, try to increase the maximum memory allocation pool for the JVM in `gradle.properties`. + +``` +org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=512m +``` \ No newline at end of file diff --git a/src/guide/connecting.md b/src/guide/connecting.md new file mode 100644 index 00000000..cdc2aa17 --- /dev/null +++ b/src/guide/connecting.md @@ -0,0 +1,157 @@ +# Connecting to a node + +The first step is to construct the SDK configuration. In it the environment and Greenlight node configuration is defined, whether you are using an invite code or partner credentials. + +The SDK uses the config working directory to store the state of the SDK instance. Once a connection has been established with a node, the working directory can only be used for that node. When handling multiple instances of the SDK, one per node, each needs to have a different working directory defined. + +Now you are ready to interact with the SDK. + + +
Rust
+
+ +```rust,ignore +{{#include ../../snippets/rust/src/getting_started.rs:init-sdk}} +``` + +
+ +
Swift
+
+ +```swift,ignore +{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:init-sdk}} +``` + +
+ +
Kotlin
+
+ +```kotlin,ignore +{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:init-sdk}} +``` + +
+ +
React Native
+
+ +```typescript +{{#include ../../snippets/react-native/getting_started.ts:init-sdk}} +``` + +
+ +
Dart
+
+ +```dart,ignore +{{#include ../../snippets/dart_snippets/lib/getting_started.dart:init-sdk}} +``` +
+ +
Python
+
+ +```python,ignore +{{#include ../../snippets/python/src/getting_started.py:init-sdk}} +``` +
+ +
Go
+
+ +```go,ignore +{{#include ../../snippets/go/getting_started.go:init-sdk}} +``` +
+ +
C#
+
+ +```cs,ignore +{{#include ../../snippets/csharp/GettingStarted.cs:init-sdk}} +``` +
+
+ +
+

Developer note

+ +By default the config working directory is set to `./`. Some platforms may require that you use an application specific directory that is writable within the application sandbox. For example, applications running on Android or iOS. + +
+
+ +To connect to an already existing node without registering a new one, use the `restore_only` flag in the connect request. If the node does not exist it will result in an error. + + +
Rust
+
+ +```rust,ignore +{{#include ../../snippets/rust/src/getting_started.rs:init-sdk-restore-only}} +``` + +
+ +
Swift
+
+ +```swift,ignore +{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:init-sdk-restore-only}} +``` + +
+ +
Kotlin
+
+ +```kotlin,ignore +{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:init-sdk-restore-only}} +``` + +
+ +
React Native
+
+ +```typescript +{{#include ../../snippets/react-native/getting_started.ts:init-sdk-restore-only}} +``` + +
+ +
Dart
+
+ +```dart,ignore +{{#include ../../snippets/dart_snippets/lib/getting_started.dart:init-sdk-restore-only}} +``` +
+ +
Python
+
+ +```python,ignore +{{#include ../../snippets/python/src/getting_started.py:init-sdk-restore-only}} +``` +
+ +
Go
+
+ +```go,ignore +{{#include ../../snippets/go/getting_started.go:init-sdk-restore-only}} +``` +
+ +
C#
+
+ +```cs,ignore +{{#include ../../snippets/csharp/GettingStarted.cs:init-sdk-restore-only}} +``` +
+
diff --git a/src/guide/getting_started.md b/src/guide/getting_started.md index 00b77724..b9d9f178 100644 --- a/src/guide/getting_started.md +++ b/src/guide/getting_started.md @@ -25,236 +25,8 @@ To get both of them, please contact Breez via email at . -## Installing - -Breez SDK is available in several platforms. Follow the [Installing](/guide/install.md) page for instructions on how to install on your platform. - -## Connecting - -The first step is to construct the SDK configuration. In it the environment and Greenlight node configuration is defined, whether you are using an invite code or partner credentials. - -The SDK uses the config working directory to store the state of the SDK instance. Once a connection has been established with a node, the working directory can only be used for that node. When handling multiple instances of the SDK, one per node, each needs to have a different working directory defined. - -Now you are ready to interact with the SDK. - - -
Rust
-
- -```rust,ignore -{{#include ../../snippets/rust/src/getting_started.rs:init-sdk}} -``` - -
- -
Swift
-
- -```swift,ignore -{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:init-sdk}} -``` - -
- -
Kotlin
-
- -```kotlin,ignore -{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:init-sdk}} -``` - -
- -
React Native
-
- -```typescript -{{#include ../../snippets/react-native/getting_started.ts:init-sdk}} -``` - -
- -
Dart
-
- -```dart,ignore -{{#include ../../snippets/dart_snippets/lib/getting_started.dart:init-sdk}} -``` -
- -
Python
-
- -```python,ignore -{{#include ../../snippets/python/src/getting_started.py:init-sdk}} -``` -
- -
Go
-
- -```go,ignore -{{#include ../../snippets/go/getting_started.go:init-sdk}} -``` -
- -
C#
-
- -```cs,ignore -{{#include ../../snippets/csharp/GettingStarted.cs:init-sdk}} -``` -
-
- -
-

Developer note

- -By default the config working directory is set to `./`. Some platforms may require that you use an application specific directory that is writable within the application sandbox. For example applications running on Android or iOS. - -
-
- -To connect to an already existing node without registering a new one, use the `restore_only` flag in the connect request. If the node does not exist it will result in an error. - - -
Rust
-
- -```rust,ignore -{{#include ../../snippets/rust/src/getting_started.rs:init-sdk-restore-only}} -``` - -
- -
Swift
-
- -```swift,ignore -{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:init-sdk-restore-only}} -``` - -
- -
Kotlin
-
- -```kotlin,ignore -{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:init-sdk-restore-only}} -``` - -
- -
React Native
-
- -```typescript -{{#include ../../snippets/react-native/getting_started.ts:init-sdk-restore-only}} -``` - -
- -
Dart
-
- -```dart,ignore -{{#include ../../snippets/dart_snippets/lib/getting_started.dart:init-sdk-restore-only}} -``` -
- -
Python
-
- -```python,ignore -{{#include ../../snippets/python/src/getting_started.py:init-sdk-restore-only}} -``` -
- -
Go
-
- -```go,ignore -{{#include ../../snippets/go/getting_started.go:init-sdk-restore-only}} -``` -
- -
C#
-
- -```cs,ignore -{{#include ../../snippets/csharp/GettingStarted.cs:init-sdk-restore-only}} -``` -
-
- -## Getting the Node State - -At any point we can fetch our balance from the Greenlight node: - - -
Rust
-
- -```rust,ignore -{{#include ../../snippets/rust/src/getting_started.rs:fetch-balance}} -``` -
- -
Swift
-
- -```swift,ignore -{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:fetch-balance}} -``` -
- -
Kotlin
-
- -```kotlin,ignore -{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:fetch-balance}} -``` -
- -
React Native
-
- -```typescript -{{#include ../../snippets/react-native/getting_started.ts:fetch-balance}} -``` -
- -
Dart
-
- -```dart,ignore -{{#include ../../snippets/dart_snippets/lib/getting_started.dart:fetch-balance}} -``` -
- -
Python
-
- -```python,ignore -{{#include ../../snippets/python/src/getting_started.py:fetch-balance}} -``` -
- -
Go
-
- -```go,ignore -{{#include ../../snippets/go/getting_started.go:fetch-balance}} -``` -
- -
C#
-
- -```cs,ignore -{{#include ../../snippets/csharp/GettingStarted.cs:fetch-balance}} -``` -
-
- -You are now ready to receive a Lightning [payment](/guide/payments.md). +## Next steps +- **[Installing the Breez SDK](/guide/install.md)** +- **[Connecting to a node](/guide/connecting.md)** +- **[Getting the node state](/guide/node_state.md)** +- **[Adding logging](/guide/logging.md)** diff --git a/src/guide/install.md b/src/guide/install.md index 28364957..962deacf 100644 --- a/src/guide/install.md +++ b/src/guide/install.md @@ -1,6 +1,6 @@ -# Installing +# Installing the Breez SDK -The Breez SDK is available in the following platforms: +The Breez SDK is available for several platforms. Follow the instructions below on how to install on your platform: ## iOS/Swift @@ -56,7 +56,7 @@ dependencies { } ``` -See [the example](https://github.com/breez/breez-sdk-examples/tree/main/Android) for more details +Please check the [troubleshooting guide](/guide/android_troubleshooting.md) if you are having problems compiling your Android application. ## React Native diff --git a/src/guide/lnurlpay.md b/src/guide/lnurlpay.md index 2f65a6a4..89f52ec9 100644 --- a/src/guide/lnurlpay.md +++ b/src/guide/lnurlpay.md @@ -76,7 +76,7 @@ The service receives the response from the app and forwards it to the sender. ### Step 4: Fetching a bolt11 invoice -The sender fetchs a bolt11 invoice by invoking a GET request to the callback_url with adding a specific amount as a query parameter. For example: +The sender fetches a bolt11 invoice by invoking a GET request to the callback_url with adding a specific amount as a query parameter. For example: ``` https://app.domain.com/lnurlpay/invoice?amount=1000 ``` diff --git a/src/guide/logging.md b/src/guide/logging.md new file mode 100644 index 00000000..05d32357 --- /dev/null +++ b/src/guide/logging.md @@ -0,0 +1,69 @@ +# Adding logging + +Breez SDK implements detailed logging via a streaming interface you can manage within your application. The log entries are split into several levels that you can filter and store as desired within your application, for example, by appending them to a log file. + + +
Rust
+
+ +```rust,ignore +{{#include ../../snippets/rust/src/getting_started.rs:logging}} +``` +
+ +
Swift
+
+ +```swift,ignore +{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:logging}} +``` +
+ +
Kotlin
+
+ +```kotlin,ignore +{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:logging}} +``` +
+ +
React Native
+
+ +```typescript +{{#include ../../snippets/react-native/getting_started.ts:logging}} +``` +
+ +
Dart
+
+ +```dart,ignore +{{#include ../../snippets/dart_snippets/lib/getting_started.dart:logging}} +``` +
+ +
Python
+
+ +```python,ignore +{{#include ../../snippets/python/src/getting_started.py:logging}} +``` +
+ +
Go
+
+ +```go,ignore +{{#include ../../snippets/go/getting_started.go:logging}} +``` +
+ +
C#
+
+ +```cs,ignore +{{#include ../../snippets/csharp/GettingStarted.cs:logging}} +``` +
+
diff --git a/src/guide/node_state.md b/src/guide/node_state.md new file mode 100644 index 00000000..fdbc7444 --- /dev/null +++ b/src/guide/node_state.md @@ -0,0 +1,71 @@ +# Getting the node state + +At any point we can fetch our balance from the node and check the lightning and onchain balances. + + +
Rust
+
+ +```rust,ignore +{{#include ../../snippets/rust/src/getting_started.rs:fetch-balance}} +``` +
+ +
Swift
+
+ +```swift,ignore +{{#include ../../snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift:fetch-balance}} +``` +
+ +
Kotlin
+
+ +```kotlin,ignore +{{#include ../../snippets/kotlin_mpp_lib/shared/src/commonMain/kotlin/com/example/kotlinmpplib/GettingStarted.kt:fetch-balance}} +``` +
+ +
React Native
+
+ +```typescript +{{#include ../../snippets/react-native/getting_started.ts:fetch-balance}} +``` +
+ +
Dart
+
+ +```dart,ignore +{{#include ../../snippets/dart_snippets/lib/getting_started.dart:fetch-balance}} +``` +
+ +
Python
+
+ +```python,ignore +{{#include ../../snippets/python/src/getting_started.py:fetch-balance}} +``` +
+ +
Go
+
+ +```go,ignore +{{#include ../../snippets/go/getting_started.go:fetch-balance}} +``` +
+ +
C#
+
+ +```cs,ignore +{{#include ../../snippets/csharp/GettingStarted.cs:fetch-balance}} +``` +
+
+ +You are now ready to receive a Lightning [payment](/guide/payments.md). diff --git a/src/guide/payment_notification.md b/src/guide/payment_notification.md index 1c29d7c3..d7bb92b6 100644 --- a/src/guide/payment_notification.md +++ b/src/guide/payment_notification.md @@ -8,13 +8,30 @@ The process involves using a Notification Delivery Service (NDS) acting as an in ![receive via notifications_2](https://github.com/breez/breez-sdk-docs/assets/31890660/75e7cac6-4480-453d-823b-f52bd6757ce9) +### Push notification data + +When receiving POST request data on the webhook URL, the NDS should get the `token`, `platform` and optional `app_data` from the URL params. If necessary, convert the token to a token that can be sent to the push notification service. Then format the data to be sent to the push notification service, which includes converting any JSON data into a string format. + +By default the Notification Plugin should receive the push notification data in the following format: + +```json +{ + "notification_type": "payment_received", + "notification_payload": "{ \"payment_hash\": \"\" }", + "app_data": "" +} +``` +The structure and fields of this data can be changed by [customising the push messages](/notifications/custom_messages.md) handling in the Notification Plugin to reflect how your NDS sends this data over push notifications. + ## Use cases The Notification Plugin handles several use cases by default to automatically process push notifications sent via the NDS from when an SDK service calls the registered webhook. If your use case isn't covered by the Notification Plugin, you can extend the plugin to [handle custom notifications](/notifications/custom_notifications.md). #### Receiving a payment -Payments are routed through an LSP to the user's node. When an LSP intercepts a payment, the LSP calls the registered webhook with the details of the payment. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and wait for the payment to be processed by the Breez SDK. The `payment_received` notification type has the following format: +Payments are routed through an LSP to the user's node. When an LSP intercepts a payment, the LSP calls the registered webhook with the details of the payment. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and wait for the payment to be processed by the Breez SDK. + +The `payment_received` notification type will be received by the webhook in the following format: ```json { "template": "payment_received", @@ -26,7 +43,9 @@ Payments are routed through an LSP to the user's node. When an LSP intercepts a #### Confirming a swap -When receiving a payment via a onchain address, the swap address needs to be monitored until the funds are confirmed onchain before the swap is executed. A chain service is used to monitor the address for confirmed funds. Once funds are confirmed, the chain service calls the registered webhook with the address. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and redeem the swap. The `address_txs_confirmed` notification type has the following format: +When receiving a payment via a onchain address, the swap address needs to be monitored until the funds are confirmed onchain before the swap is executed. A chain service is used to monitor the address for confirmed funds. Once funds are confirmed, the chain service calls the registered webhook with the address. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and redeem the swap. + +The `address_txs_confirmed` notification type will be received by the webhook in the following format: ```json { "template": "address_txs_confirmed", @@ -38,9 +57,11 @@ When receiving a payment via a onchain address, the swap address needs to be mon #### Handling LNURL pay requests -Having the ability to process push notifications when the application is in the background or closed also opens up the ability to handle payment requests from a static LNURL address. To do this the application also needs to register a webook with an [LNURL-pay service](lnurlpay.md), then when the LNURL service receives a request on the static LNURL address, it will forward it via the NDS to the application. The Notification Plugin handles the two-step flow for fulfilling these requests. +Having the ability to process push notifications when the application is in the background or closed also opens up the ability to handle payment requests from a static LNURL address. To do this the application also needs to register a webhook with an [LNURL-pay service](lnurlpay.md), then when the LNURL service receives a request on the static LNURL address, it will forward it via the NDS to the application. The Notification Plugin handles the two-step flow for fulfilling these requests. + +Firstly the LNURL service receives a request for LNURL-pay information to get the min/max amount that can be received. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and send a response back to the LNURL service based on the node info. -Firstly the LNURL service receives a request for LNURL-pay information to get the min/max amount that can be received. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and send a response back to the LNURL service based on the node info. The `lnurlpay_info` notification type has the following format: +The `lnurlpay_info` notification type will be received by the webhook in the following format: ```json { "template": "lnurlpay_info", @@ -50,7 +71,9 @@ Firstly the LNURL service receives a request for LNURL-pay information to get th } } ``` -Secondly the LNURL service receives a request for an invoice based on the selected amount to pay. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and call receive payment for the requested amount. The resulting invoice is then returned to the LNURL service. The `lnurlpay_invoice` notification type has the following format: +Secondly the LNURL service receives a request for an invoice based on the selected amount to pay. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and call receive payment for the requested amount. The resulting invoice is then returned to the LNURL service. + +The `lnurlpay_invoice` notification type will be received by the webhook in the following format: ```json { "template": "lnurlpay_invoice", diff --git a/src/guide/production.md b/src/guide/production.md index d93220c5..6d258b3f 100644 --- a/src/guide/production.md +++ b/src/guide/production.md @@ -70,15 +70,29 @@ To move your project to production, you will have to replace the evaluation invi To obtain a certificate for a production environment, please register [here](https://greenlight.blockstream.com/) and make sure to notify your LSP(s). +## Applying certificates + +The certificates received from Blockstream should be contained with a zip file. Within the zip file should be a `.crt` and a `.pem` file, these are the certificate and private key files. To use these files with the Breez SDK each file needs to be read as binary/byte data, inserting the `.crt` data as the device cert and the `.pem` data as the device key. +
+

Developer note

+Leave the file contents as is, manipulating the file contents will result in transport errors. +
    +
  • Do not strip the headers and footers from the file contents
    (BEGIN CERTIFICATE / END CERTIFICATE / BEGIN PRIVATE KEY / END PRIVATE KEY)
  • +
  • Do not use only part of the certificate
  • +
+
+ ## Production checklist There are some use cases where you need to verify that they are implemented correctly. Here is a checklist you can use to verify that your application is production ready. -- **Closed channels**: Make sure you allow your users to redeem their onchain balance in case their channels were closed. See [Handling channel closures](closed_channels.md) +- **Add logging**: Add sufficient logging into your application to diagnose any issues users are having. For more information: [Adding logging](logging.md). + +- **Handle closed channels**: Make sure you allow your users to redeem their onchain balance in case their channels were closed. For more information: [Handling channel closures](closed_channels.md). -- **Pending payments**: Payments always contain a status field that can be used to determine if the payment was completed or not. Make sure you handle the case where the payment is still pending by showing the correct status to the user. +- **Display pending payments**: Payments always contain a status field that can be used to determine if the payment was completed or not. Make sure you handle the case where the payment is still pending by showing the correct status to the user. -- **Handle swaps refunds**: Swaps that are the result of [Receiving an On-Chain Transaction](receive_onchain.md) may not be completed and change to `Refundable` state. Make sure you handle this case correctly by allowing the user to retry the [refund](receive_onchain.html#refund-a-swap) with different fees as long as the refund is not confirmed. A confirmed refund changes the swap status from `Refundable` to `Completed`. +- **Enable swaps refunds**: Swaps that are the result of [Receiving an On-Chain Transaction](receive_onchain.md) may not be completed and change to `Refundable` state. Make sure you handle this case correctly by allowing the user to retry the [refund](receive_onchain.html#refund-a-swap) with different fees as long as the refund is not confirmed. A confirmed refund changes the swap status from `Refundable` to `Completed`. -- **Swap-in / swap-out fees**: When sending or receiving on-chain, make sure to clearly show the expected fees involved, as well as the send / receive amounts. +- **Expose swap fees**: When sending or receiving on-chain, make sure to clearly show the expected fees involved, as well as the send / receive amounts. -- **Connect**: Create a Lightning node (connect) only when users are interested to receive payments with Lightning (not on the app startup). \ No newline at end of file +- **Connect on-demand**: Create a Lightning node (connect) only when users are interested to receive payments with Lightning (not on the app startup). diff --git a/src/guide/send_spontaneous_payment.md b/src/guide/send_spontaneous_payment.md index 9f1e9cc1..7eb69530 100644 --- a/src/guide/send_spontaneous_payment.md +++ b/src/guide/send_spontaneous_payment.md @@ -70,7 +70,7 @@ They can even be spontaneous payments to a node without a bolt11 invoice. ## Adding Extra TLVs to a Spontaneous Payment -A list of extra TLV data can also be sent with the sponaneous payment. +A list of extra TLV data can also be sent with the spontaneous payment.
Rust
diff --git a/src/guide/service_status.md b/src/guide/service_status.md index 53ee4aa1..62c0f865 100644 --- a/src/guide/service_status.md +++ b/src/guide/service_status.md @@ -1,7 +1,7 @@ # Retrieving service status You can check the general health status of the services provided by the Breez SDK. -The response status will inform you if there is maintenance occurring, a service distruption or the services are operational. +The response status will inform you if there is maintenance occurring, a service disruption or the services are operational.
Rust
diff --git a/src/notifications/android_plugin.md b/src/notifications/android_plugin.md index d579c9e6..7920ff0e 100644 --- a/src/notifications/android_plugin.md +++ b/src/notifications/android_plugin.md @@ -83,7 +83,7 @@ class ExampleFcmService : MessagingService, FirebaseMessagingService() { } ``` -Now lets add the foreground service implementation. This should implement the notification plugin `ForegroundService` class, which handles the incoming notification intent and processes the event. To properly implement this, your class needs to override the `onCreate`, `getConnectRequest` and `getServiceConfig` functions. The `getConnectRequest` function is called by the `ForegroundService` to get a BreezSDK `ConnectRequest` which contains the data necessary to connect the SDK to the node. This data includes the Breez API key, the `Config` with it's workingDir and the node seed. +Now lets add the foreground service implementation. This should implement the notification plugin `ForegroundService` class, which handles the incoming notification intent and processes the event. To properly implement this, your class needs to override the `onCreate`, `getConnectRequest` and `getServiceConfig` functions. The `getConnectRequest` function is called by the `ForegroundService` to get a BreezSDK `ConnectRequest` which contains the data necessary to connect the SDK to the node. This data includes the Breez API key, the `Config` with it's `workingDir` and the node seed.

Developer note

diff --git a/src/notifications/custom_messages.md b/src/notifications/custom_messages.md new file mode 100644 index 00000000..a54c3f53 --- /dev/null +++ b/src/notifications/custom_messages.md @@ -0,0 +1,67 @@ +# Customising push messages + +The Notification Plugin by default handles a specific format of push notification message data sent by the NDS: +```json +{ + "notification_type": "payment_received", + "notification_payload": "{ \"payment_hash\": \"\" }", + "app_data": "" +} +``` + +If you want to customise the structure or field names of the push notification message data handled by the Notification Plugin, you can follow the code example below for adding these to iOS and Android. In these examples we replace the `notification_type` and `notification_payload` fields with `custom_type` and `custom_payload`. + + +
Swift
+
+First you need to override the getTaskFromNotification function in the implementation of the SDKNotificationService class. Then from content.userInfo use the custom fields to get the notification type and payload: + +```swift,ignore +class NotificationService: SDKNotificationService { + // Override the `getTaskFromNotification` function + override func getTaskFromNotification() -> TaskProtocol? { + guard let content = bestAttemptContent else { return nil } + guard let notificationType = content.userInfo["custom_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["custom_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 + } + } +} +``` + +
+
Kotlin
+
+First you need to change the RemoteMessage.asMessage function in the implementation of the MessagingService class. Then from data use the custom fields to get the notification type and payload: + +```kotlin,ignore +class ExampleFcmService : MessagingService, FirebaseMessagingService() { + // Change the `RemoteMessage.asMessage` function + private fun RemoteMessage.asMessage(): Message? { + return data["custom_type"]?.let { + Message(data["custom_type"], data["custom_payload"]) + } + } +} +``` + +
+
diff --git a/src/notifications/getting_started.md b/src/notifications/getting_started.md index 0e8fec9c..84c60bda 100644 --- a/src/notifications/getting_started.md +++ b/src/notifications/getting_started.md @@ -8,13 +8,30 @@ The process involves using a Notification Delivery Service (NDS) acting as an in ![receive via notifications_2](https://github.com/breez/breez-sdk-docs/assets/31890660/75e7cac6-4480-453d-823b-f52bd6757ce9) +### Push notification data + +When receiving POST request data on the webhook URL, the NDS should get the `token`, `platform` and optional `app_data` from the URL params. If necessary, convert the token to a token that can be sent to the push notification service. Then format the data to be sent to the push notification service, which includes converting any JSON data into a string format. + +By default the Notification Plugin should receive the push notification data in the following format: + +```json +{ + "notification_type": "payment_received", + "notification_payload": "{ \"payment_hash\": \"\" }", + "app_data": "" +} +``` +The structure and fields of this data can be changed by [customising the push messages](custom_messages.md) handling in the Notification Plugin to reflect how your NDS sends this data over push notifications. + ## Use cases The Notification Plugin handles several use cases by default to automatically process push notifications sent via the NDS from when an SDK service calls the registered webhook. If your use case isn't covered by the Notification Plugin, you can extend the plugin to [handle custom notifications](custom_notifications.md). #### Receiving a payment -Payments are routed through an LSP to the user's node. When an LSP intercepts a payment, the LSP calls the registered webhook with the details of the payment. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and wait for the payment to be processed by the Breez SDK. The `payment_received` notification type has the following format: +Payments are routed through an LSP to the user's node. When an LSP intercepts a payment, the LSP calls the registered webhook with the details of the payment. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and wait for the payment to be processed by the Breez SDK. + +The `payment_received` notification type will be received by the webhook in the following format: ```json { "template": "payment_received", @@ -26,7 +43,9 @@ Payments are routed through an LSP to the user's node. When an LSP intercepts a #### Confirming a swap -When receiving a payment via a onchain address, the swap address needs to be monitored until the funds are confirmed onchain before the swap is executed. A chain service is used to monitor the address for confirmed funds. Once funds are confirmed, the chain service calls the registered webhook with the address. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and redeem the swap. The `address_txs_confirmed` notification type has the following format: +When receiving a payment via a onchain address, the swap address needs to be monitored until the funds are confirmed onchain before the swap is executed. A chain service is used to monitor the address for confirmed funds. Once funds are confirmed, the chain service calls the registered webhook with the address. The Notification Plugin when receiving this notification from the NDS will connect to the Breez SDK and redeem the swap. + +The `address_txs_confirmed` notification type will be received by the webhook in the following format: ```json { "template": "address_txs_confirmed", @@ -38,9 +57,11 @@ When receiving a payment via a onchain address, the swap address needs to be mon #### Handling LNURL pay requests -Having the ability to process push notifications when the application is in the background or closed also opens up the ability to handle payment requests from a static LNURL address. To do this the application also needs to register a webook with an [LNURL-pay service](/guide/lnurlpay.md), then when the LNURL service receives a request on the static LNURL address, it will forward it via the NDS to the application. The Notification Plugin handles the two-step flow for fulfilling these requests. +Having the ability to process push notifications when the application is in the background or closed also opens up the ability to handle payment requests from a static LNURL address. To do this the application also needs to register a webhook with an [LNURL-pay service](/guide/lnurlpay.md), then when the LNURL service receives a request on the static LNURL address, it will forward it via the NDS to the application. The Notification Plugin handles the two-step flow for fulfilling these requests. + +Firstly the LNURL service receives a request for LNURL-pay information to get the min/max amount that can be received. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and send a response back to the LNURL service based on the node info. -Firstly the LNURL service receives a request for LNURL-pay information to get the min/max amount that can be received. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and send a response back to the LNURL service based on the node info. The `lnurlpay_info` notification type has the following format: +The `lnurlpay_info` notification type will be received by the webhook in the following format: ```json { "template": "lnurlpay_info", @@ -50,7 +71,9 @@ Firstly the LNURL service receives a request for LNURL-pay information to get th } } ``` -Secondly the LNURL service receives a request for an invoice based on the selected amount to pay. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and call receive payment for the requested amount. The resulting invoice is then returned to the LNURL service. The `lnurlpay_invoice` notification type has the following format: +Secondly the LNURL service receives a request for an invoice based on the selected amount to pay. The LNURL service calls the registered webhook and when receiving this notification, the Notification Plugin will connect to the Breez SDK and call receive payment for the requested amount. The resulting invoice is then returned to the LNURL service. + +The `lnurlpay_invoice` notification type will be received by the webhook in the following format: ```json { "template": "lnurlpay_invoice", diff --git a/src/notifications/ios_plugin.md b/src/notifications/ios_plugin.md index af5c51b3..35111677 100644 --- a/src/notifications/ios_plugin.md +++ b/src/notifications/ios_plugin.md @@ -17,11 +17,11 @@ More installation methods, including with the Swift Package Manager, can be foun You're ready to add some Swift code to implement the Notification Plugin in your NotificationService target. In Xcode, in the `NotificationService` folder, open the Swift file named `NotificationService.swift`. -This Swift file should implement the Notification Plugin's `SDKNotificationService` class. The `SDKNotificationService` class handles the incoming notification content and processes the event. To properly implement this class the NotificationService needs to override at least the `getConnectRequest` function. The `getConnectRequest` function is called by the `SDKNotificationService` to get a BreezSDK `ConnectRequest` which contains the data necessary to connect the SDK to the node. This data includes the Breez API key, the `Config` with it's workingDir and the node seed. +This Swift file should implement the Notification Plugin's `SDKNotificationService` class. The `SDKNotificationService` class handles the incoming notification content and processes the event. To properly implement this class the NotificationService needs to override at least the `getConnectRequest` function. The `getConnectRequest` function is called by the `SDKNotificationService` to get a BreezSDK `ConnectRequest` which contains the data necessary to connect the SDK to the node. This data includes the Breez API key, the `Config` with it's `workingDir` and the node seed.

Developer note

-When using the Notification Plugin in iOS, it is important to note that the Config workingDir needs to be set to the app group's shared directory in both the NotificationService target and in the main application target, wheather that is a Swift, Flutter or React Native based application. +When using the Notification Plugin in iOS, it is important to note that the Config workingDir needs to be set to the app group's shared directory in both the NotificationService target and in the main application target, whether that is a Swift, Flutter or React Native based application.

Developer note

diff --git a/src/notifications/logging.md b/src/notifications/logging.md index eacd49dd..a0e6cb37 100644 --- a/src/notifications/logging.md +++ b/src/notifications/logging.md @@ -5,7 +5,7 @@ You can override the default logger used by the Notification Plugin to use your
Swift
-In iOS lets use the XCGLogger to handle logging to a seperate log file in the app group's shared directory. +In iOS lets use the XCGLogger to handle logging to a separate log file in the app group's shared directory. ```swift,ignore import BreezSDK @@ -103,7 +103,7 @@ class ExampleFcmService : MessagingService, FirebaseMessagingService() { } ``` -When the foreground service is created, initialise the Breek SDK log stream and subscribe to log entries +When the foreground service is created, initialise the Breez SDK log stream and subscribe to log entries ```kotlin,ignore package com.example.application