diff --git a/.gitignore b/.gitignore
index 7585238..0ef6ca8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
book
+.DS_Store
+.idea
diff --git a/src/guide/Installing.md b/src/guide/Installing.md
deleted file mode 100644
index 55af1c5..0000000
--- a/src/guide/Installing.md
+++ /dev/null
@@ -1 +0,0 @@
-# Install
diff --git a/src/guide/connecting_lsp.md b/src/guide/connecting_lsp.md
index 585417c..b16af80 100644
--- a/src/guide/connecting_lsp.md
+++ b/src/guide/connecting_lsp.md
@@ -25,6 +25,35 @@ do {
}
```
+
+
Adroid
+
+
+Based on the API key provided to the Breez SDK, a default LSP is selected for your node to provide liquidity to it. To get the information about the selected LSP you can do the following:
+
+```kotlin
+try {
+ val lspId = sdk.lspId()
+ if (lspId != null) {
+ val lspInfo = sdk.fetchLspInfo(lspId)
+ } else {
+ // Handle no lsp id scenario
+ }
+} catch (e: Exception) {
+ // Handle error
+}
+```
+
+When you have selected an LSP you may then connect to it.
+
+```kotlin
+try {
+ sdk.connectLsp(lspId)
+} catch (e: Exception) {
+ // Handle error
+}
+```
+
React Native
diff --git a/src/guide/fiat_currencies.md b/src/guide/fiat_currencies.md
index 5995c33..0648af0 100644
--- a/src/guide/fiat_currencies.md
+++ b/src/guide/fiat_currencies.md
@@ -1,9 +1,59 @@
# Supporting fiat currencies
+Android
+
+In order to list the available fiat currencies.
+
+```kotlin
+try {
+ val fiatCurrencyList = sdk.listFiatCurrencies()
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+To get the current BTC rate for the currencies.
+
+```kotlin
+try {
+ val fiatRatesMap = sdk.fetchFiatRates()
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+At the example project you can see these methods combined
+
+```kotlin
+fun fiatCurrenciesAndRate(): Map = try {
+ val fiatCurrencies = sdk.listFiatCurrencies()
+ val fiatRates = sdk.fetchFiatRates()
+
+ val ratesMap = mutableMapOf()
+ for (rate in fiatRates) {
+ ratesMap[rate.coin.lowercase()] = rate
+ }
+
+ val sorted = fiatCurrencies.sortedBy { it.info.name }
+ val result = LinkedHashMap()
+ for (currency in sorted) {
+ val rate = ratesMap[currency.id.lowercase()]
+ if (rate != null) {
+ result[currency] = rate
+ }
+ }
+
+ result
+} catch (e: Throwable) {
+ // Handle error
+ emptyMap()
+}
+```
+
React Native
-In order to list the availiable fiat currencies.
+In order to list the available fiat currencies.
```typescript
try {
@@ -25,7 +75,7 @@ try {
Dart
-In order to list the availiable fiat currencies.
+In order to list the available fiat currencies.
```dart
try {
@@ -49,7 +99,7 @@ try {
Python
-In order to list the availiable fiat currencies.
+In order to list the available fiat currencies.
```python
try:
@@ -71,7 +121,7 @@ except Exception as error:
Go
-In order to list the availiable fiat currencies.
+In order to list the available fiat currencies.
```go
fiatCurrencies, err := sdkServices.ListFiatCurrencies()
@@ -85,7 +135,7 @@ fiatRates, err := sdkServices.FetchFiatRates()
C#
-In order to list the availiable fiat currencies.
+In order to list the available fiat currencies.
```cs
try
diff --git a/src/guide/getting_started.md b/src/guide/getting_started.md
index bef073a..266a1c3 100644
--- a/src/guide/getting_started.md
+++ b/src/guide/getting_started.md
@@ -89,6 +89,41 @@ do {
+Android
+
+
+## Connecting
+```kotlin
+// SDK events listener
+class SDKListener : EventListener {
+ override fun onEvent(e: BreezEvent) {
+ Log.v("SDKListener", "Received event $e")
+ }
+}
+
+// Select your seed, invite code and eviroment
+val seed = mnemonicToSeed("")
+val inviteCode = "your invite code"
+val environmentType = EnvironmentType.PRODUCTION
+
+// Create the default config
+val greenlightNodeConfig = GreenlightNodeConfig(null, inviteCode)
+val nodeConfig = NodeConfig.Greenlight(greenlightNodeConfig)
+val config = defaultConfig(environmentType, inviteCode, nodeConfig)
+
+// Customize the config object according to your needs
+config.workingDir = "path to an existing directory"
+
+try {
+ // Connect to the Breez SDK make it ready for use
+ val sdk = connect(config, seed, SDKListener())
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+
+
React Native
@@ -294,6 +329,20 @@ do {
```
+Android
+
+
+```kotlin
+try {
+ val nodeInfo = sdk.nodeInfo()
+ val lnBalance = nodeInfo?.channelsBalanceMsat
+ val onchainBalance = nodeInfo?.onchainBalanceMsat
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+
React Native
diff --git a/src/guide/install.md b/src/guide/install.md
index 5dd303a..6cdf43c 100644
--- a/src/guide/install.md
+++ b/src/guide/install.md
@@ -2,24 +2,6 @@
The Breez SDK is available in the following platforms:
-## Android
-
-We recommend integrating the Breez SDK as Gradle dependency from [our Maven repository](https://mvn.breez.technology/releases).
-
-To do so, add the following to your Gradle dependencies:
-
-```gradle
-repositories {
- maven {
- url("https://mvn.breez.technology/releases")
- }
-}
-
-dependencies {
- implementation("breez_sdk:bindings-android:")
-}
-```
-
## iOS
We support integration via the [Swift Package Manager](https://www.swift.org/package-manager/) and via [CocoaPods](https://cocoapods.org/).
@@ -56,6 +38,26 @@ target '")
+}
+```
+
+See [the example](https://github.com/breez/breez-sdk/tree/main/libs/sdk-bindings/bindings-android/example) for more details
+
## React Native
We recommmend using the official npm package:
diff --git a/src/guide/lnurl_auth.md b/src/guide/lnurl_auth.md
index 4d5defb..f65b447 100644
--- a/src/guide/lnurl_auth.md
+++ b/src/guide/lnurl_auth.md
@@ -49,6 +49,28 @@ do {
}
```
+
+Android
+
+
+```kotlin
+// Endpoint can also be of the form:
+// keyauth://domain.com/auth?key=val
+// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…
+val lnurlAuthUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…"
+try {
+ val inputType = parseInput(lnurlPayUrl)
+ if (inputType is InputType.LnUrlAuth) {
+ when (val result = sdk.lnurlAuth(inputType.data)) {
+ LnUrlCallbackStatus.Ok -> Log.v("Breez", "Successfully authenticated")
+ is LnUrlCallbackStatus.ErrorStatus -> Log.v("Breez", "Failed to authenticate: ${result.data.reason}")
+ }
+ }
+} catch (e: Exception) {
+ // handle error
+}
+```
+
React Native
diff --git a/src/guide/lnurl_pay.md b/src/guide/lnurl_pay.md
index b7242da..86d22f2 100644
--- a/src/guide/lnurl_pay.md
+++ b/src/guide/lnurl_pay.md
@@ -41,6 +41,27 @@ do {
}
```
+Android
+
+
+```kotlin
+// Endpoint can also be of the form:
+// lnurlp://domain.com/lnurl-pay?key=val
+// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…
+val lnurlPayUrl = "lightning@address.com";
+try {
+ val inputType = parseInput(lnurlPayUrl)
+ if (inputType is InputType.LnUrlPay) {
+ val requestData = inputType.data
+ val amountSats = requestData.minSendable
+ val comment = "Any comment"
+ sdk.payLnurl(requestData, amountSats, comment)
+ }
+} catch (e: Exception) {
+ // handle error
+}
+```
+
React Native
diff --git a/src/guide/lnurl_withdraw.md b/src/guide/lnurl_withdraw.md
index d33d9c2..db6a7e8 100644
--- a/src/guide/lnurl_withdraw.md
+++ b/src/guide/lnurl_withdraw.md
@@ -40,6 +40,27 @@ do {
// handle error
}
+```
+
+Android
+
+
+```kotlin
+// Endpoint can also be of the form:
+// lnurlw://domain.com/lnurl-withdraw?key=val
+// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…
+val lnurlWithdrawUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…"
+try {
+ val inputType = parseInput(lnurlPayUrl)
+ if (inputType is InputType.LnUrlWithdraw) {
+ val requestData = inputType.data
+ val amountSats = requestData.minWithdrawable
+ val comment = "Any comment"
+ sdk.withdrawLnurl(requestData, amountSats, comment)
+ }
+} catch (e: Exception) {
+ // handle error
+}
```
React Native
diff --git a/src/guide/payments.md b/src/guide/payments.md
index 03beca0..5d64116 100644
--- a/src/guide/payments.md
+++ b/src/guide/payments.md
@@ -60,6 +60,41 @@ do {
}
```
+Android
+
+
+## Receiving Lightning Payments
+Breez SDK doesn't require you to open a channel and set up your inbound liquidity.
+Breez SDK automatically connects your node to the LSP peer and you can now receive payments:
+
+```kotlin
+try {
+ val invoice = sdk.receivePayment(3000L.toULong(), "Invoice for 3000 sats")
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+## Sending Lightning Payments
+```kotlin
+val bolt11 = "..."
+try {
+ val payment = sdk.sendPayment(bolt11, 3000L.toULong())
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+## Sending Spontaneous Lightning Payments
+```kotlin
+val nodeId = "..."
+try {
+ val payment = sdk.sendSpontaneousPayment(nodeId, 3000L.toULong())
+} catch (e: Exception) {
+ // handle error
+}
+```
+
React Native
diff --git a/src/guide/receive_onchain.md b/src/guide/receive_onchain.md
index 08e67bb..acf526c 100644
--- a/src/guide/receive_onchain.md
+++ b/src/guide/receive_onchain.md
@@ -92,6 +92,57 @@ do {
}
```
+Android
+
+
+```kotlin
+try {
+ val swapInfo = sdk.receiveOnchain()
+ // Send your funds to the bellow bitcoin address
+ val address = swapInfo.bitcoinAddress
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+Once you've sent the funds to the above address, the SDK will monitor this address for unspent confirmed outputs and use a trustless submarine swap to receive these into your Lightning node. You can always monitor the status of the current in-progress swap using the following code:
+
+```kotlin
+try {
+ val swapInfo = sdk.inProgressSwap()
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+The process of receiving funds via an on-chain address is trustless and uses a submarine swap. This means there are two ways to spend the sent funds:
+
+1. Either by a preimage that is exposed when the Lightning payment is completed - this is the positive case where the swap was successful.
+2. Or by your node when the swap didn't complete within a certain timeout - this is the negative case where your node will execute a refund.
+
+In order to execute a refund, you need to supply an on-chain address to where the refunded amount will be sent. The following code will retrieve the refundable swaps:
+
+```kotlin
+try {
+ val refundables = sdk.listRefundables()
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+Once you have a refundable swap in hand, use the following code to execute a refund:
+
+```kotlin
+val swapAddress = "..."
+val destinationAddress = "..."
+val satPerVbyte = 1.toUInt()
+try {
+ sdk.refund(swapAddress, destinationAddress, satPerVbyte)
+} catch (e: Exception) {
+ // handle error
+}
+```
+
React Native
@@ -458,7 +509,59 @@ func calculateFeesForAmount(amountMsats: Int64) -> Int64? {
```
+Android
+
+When the amount to be received exceeds the inbound liquidity of the node, a new channel will be opened by the LSP in order for the node to receive it. This can checked by retrieving the NodeState from the SDK and comparing the inbound liquidity to the amount to be received. If the amount is greater or equal to the inbound liquidity, a new channel opening is required.
+
+To calculate the fees for a channel being opened by the LSP:
+
+```kotlin
+fun calculateChannelOpeningFee(amountMsats: Long): Long? {
+ val channelOpeningFeeNeeded = isChannelOpeningFeeNeeded(amountMsats)
+ if (channelOpeningFeeNeeded) {
+ return calculateFeesForAmount(amountMsats)
+ }
+ return null
+}
+```
+
+How to detect if open channel fees are needed:
+```kotlin
+fun isChannelOpeningFeeNeeded(amountMsats: Long): Boolean {
+ try {
+ val nodeInfo = sdk.nodeInfo()
+ val inboundLiquidityMsats = nodeInfo?.inboundLiquidityMsats?.toLong()
+ if (inboundLiquidityMsats != null) {
+ return inboundLiquidityMsats <= amountMsats
+ }
+ } catch (e: Exception) {
+ // Handle error
+ }
+ return false
+}
+```
+
+LSP fees are calculated in two ways, either by a minimum fee set by the LSP or by a fee per myriad calculated based on the amount being received. If the fee calculated from the fee per myriad is less than the minimum fee, the minimum fee is used.
+
+This information can be retrieved for each LSP and then calculated:
+
+```kotlin
+fun calculateFeesForAmount(amountMsats: Long): Long? {
+ try {
+ val lspId = sdk.lspId() ?: return null
+ val lspInfo = sdk.fetchLspInfo(lspId) ?: return null
+ // We calculate the dynamic fees in millisatoshis rounded to satoshis.
+ val channelDynamicFeeMsat = amountMsats * lspInfo.channelFeePermyriad / 1000
+ return lspInfo.channelMinimumFeeMsat.coerceAtLeast(channelDynamicFeeMsat)
+ } catch (e: Exception) {
+ // Handle error
+ }
+ return null
+}
+```
+
+
React Native
diff --git a/src/guide/send_onchain.md b/src/guide/send_onchain.md
index cac5cd4..f549320 100644
--- a/src/guide/send_onchain.md
+++ b/src/guide/send_onchain.md
@@ -99,6 +99,56 @@ for rs in sdk.inProgressReverseSwaps() {
}
```
+Android
+
+
+```kotlin
+try {
+ val fees = sdk.fetchReverseSwapFees()
+ Log.v("Breez", "Percentage fee for the reverse swap service: ${fees.feesPercentage}")
+ Log.v("Breez", "Estimated miner fees in sats for locking up funds: ${fees.feesLockup}")
+ Log.v("Breez", "Estimated miner fees in sats for claiming funds: ${fees.feesClaim}")
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+The reverse swap will involve two on-chain transactions, for which the mining fees can only be estimated. They will happen
+automatically once the process is started, but the last two values above are these estimates to help you get a picture
+of the total costs.
+
+Fetching the fees also tells you what is the range of amounts you can send:
+
+```kotlin
+Log.v("Breez", "Minimum amount, in sats: ${fees.min}")
+Log.v("Breez", "Maximum amount, in sats: ${fees.max}")
+```
+
+Once you checked the fees are acceptable, you can start the reverse swap:
+
+```kotlin
+val address = "bc1.."
+val amountSat = 123L.toULong()
+val satPerVbyte = 1L.toULong()
+try {
+ sdk.sendOnchain(amountSat, address, fees.feesHash, satPerVbyte)
+} catch (e: Exception) {
+ // handle error
+}
+```
+
+Starting the reverse swap will trigger a HODL invoice payment, which will only be settled if the entire swap completes.
+This means you will see an outgoing pending payment in your list of payments, which locks those funds until the invoice
+is either settled or cancelled. This will happen automatically at the end of the reverse swap.
+
+You can check its status with:
+
+```kotlin
+for (rs in sdk.inProgressReverseSwaps()) {
+ Log.v("Breez", "Reverse swap ${rs.id} in progress, status is ${rs.status}")
+}
+```
+
React Native