From f78d283a03b2ba586f59767478040bc7bfce7aef Mon Sep 17 00:00:00 2001 From: Ross Savage Date: Thu, 20 Jun 2024 11:56:52 +0200 Subject: [PATCH] Add logging section --- snippets/csharp/GettingStarted.cs | 23 ++ .../dart_snippets/lib/getting_started.dart | 10 + snippets/go/getting_started.go | 15 ++ .../example/kotlinmpplib/GettingStarted.kt | 16 ++ snippets/python/src/getting_started.py | 11 + snippets/react-native/getting_started.ts | 14 +- snippets/react-native/production.ts | 2 +- snippets/rust/src/getting_started.rs | 15 +- .../Sources/GettingStarted.swift | 12 + src/SUMMARY.md | 5 +- src/guide/connecting.md | 157 ++++++++++++ src/guide/getting_started.md | 238 +----------------- src/guide/install.md | 4 +- src/guide/logging.md | 69 +++++ src/guide/node_state.md | 71 ++++++ src/guide/production.md | 10 +- 16 files changed, 429 insertions(+), 243 deletions(-) create mode 100644 src/guide/connecting.md create mode 100644 src/guide/logging.md create mode 100644 src/guide/node_state.md diff --git a/snippets/csharp/GettingStarted.cs b/snippets/csharp/GettingStarted.cs index 76ee4708..1f3fab26 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 + { + sdk = 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/dart_snippets/lib/getting_started.dart b/snippets/dart_snippets/lib/getting_started.dart index 9e56933c..cd331449 100644 --- a/snippets/dart_snippets/lib/getting_started.dart +++ b/snippets/dart_snippets/lib/getting_started.dart @@ -52,3 +52,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/go/getting_started.go b/snippets/go/getting_started.go index 395ac9d4..20dedbe6 100644 --- a/snippets/go/getting_started.go +++ b/snippets/go/getting_started.go @@ -71,3 +71,18 @@ 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/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/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/react-native/getting_started.ts b/snippets/react-native/getting_started.ts index 4131988e..296fad14 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, + LogEntry, + setLogStream } from '@breeztech/react-native-breez-sdk' const exampleGettingStarted = async () => { @@ -78,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 69953a5f..92d04f79 100644 --- a/snippets/react-native/production.ts +++ b/snippets/react-native/production.ts @@ -6,7 +6,7 @@ import { const productionNodeConfig = (): NodeConfig => { // ANCHOR: moving-to-production - // Read in your Greenlight credentials from the file file + // Read in your Greenlight credentials from the file // system, environment variable or build config const deviceKey: number[] = [] const deviceCert: number[] = [] 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/swift/BreezSDKExamples/Sources/GettingStarted.swift b/snippets/swift/BreezSDKExamples/Sources/GettingStarted.swift index b20e8357..3b204846 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(log_stream: SDKLogStream()) +} +// ANCHOR_END: logging diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1eb91db0..4302ddcd 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -3,7 +3,10 @@ # API Overview - [Getting Started](guide/getting_started.md) -- [Installing](guide/install.md) + - [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) - [Paying in Lightning](guide/payments.md) - [Receiving payments](guide/receive_payment.md) - [Sending payments](guide/send_payment.md) diff --git a/src/guide/connecting.md b/src/guide/connecting.md new file mode 100644 index 00000000..7b603503 --- /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..f0d5d514 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](install.md)** +- **[Connecting to a node](connecting.md)** +- **[Getting the node state](node_state.md)** +- **[Adding logging](logging.md)** diff --git a/src/guide/install.md b/src/guide/install.md index 23ee788a..6160a9c1 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 diff --git a/src/guide/logging.md b/src/guide/logging.md new file mode 100644 index 00000000..51573326 --- /dev/null +++ b/src/guide/logging.md @@ -0,0 +1,69 @@ +# Adding logging + +The Breez SDK implements detailed logging via a streaming interface so you can manage within your application. The log entries are split into several levels that you can filter and store how you want within your application, for example 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/production.md b/src/guide/production.md index a537c22f..6d258b3f 100644 --- a/src/guide/production.md +++ b/src/guide/production.md @@ -85,12 +85,14 @@ Leave the file contents as is, manipulating the file contents will result in tra ## 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. +- **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). -- **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. +- **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. -- **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`. +- **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`. -- **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. +- **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 on-demand**: create a Lightning node (connect) only when users are interested to receive payments with Lightning (not on the app startup). +- **Connect on-demand**: Create a Lightning node (connect) only when users are interested to receive payments with Lightning (not on the app startup).