Merge pull request #39 from breez/ok300-doc-dynamic-fees

Update receive_onchain with optional user-selected dynamic fees arg
This commit is contained in:
ok300
2023-09-04 22:29:45 +02:00
committed by GitHub
11 changed files with 335 additions and 453 deletions

View File

@@ -5,11 +5,13 @@
- [Installing](guide/install.md)
- [Getting Started](guide/getting_started.md)
- [Lightning payments](guide/payments.md)
- [Connecting to an LSP](guide/connecting_lsp.md)
- [Receiving an on-chain transaction](guide/receive_onchain.md)
- [Sending an on-chain transaction](guide/send_onchain.md)
- [Connecting to an LSP](guide/connecting_lsp.md)
- [Using LNURL](guide/lnurl.md)
- [LNURL-Pay](guide/lnurl_pay.md)
- [LNURL-Withdraw](guide/lnurl_withdraw.md)
- [LNURL-Auth](guide/lnurl_auth.md)
- [Supporting fiat currencies](guide/fiat_currencies.md)
- [Buy Bitcoin](guide/buy_btc.md)

106
src/guide/buy_btc.md Normal file
View File

@@ -0,0 +1,106 @@
# Buy Bitcoin
This section of the Breez SDK documentation provides an example on purchasing Bitcoin using Moonpay as the provider. The example code snippet demonstrates how to initiate a Bitcoin purchase transaction using the Breez SDK.
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
let res = sdk.buy_bitcoin(
BuyBitcoinRequest {
provider: BuyBitcoinProvider::Moonpay,
opening_fee_params: None})
.await?;
```
</section>
<div slot="title">Swift</div>
<section>
```swift
do {
let buyBitcoinResponse = try sdk.buyBitcoin(
req: BuyBitcoinRequest(provider: .moonpay))
} catch {
// handle error
}
```
</section>
<div slot="title">Android</div>
<section>
```kotlin,ignore
// TODO add docs
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
try {
let buyBitcoinResponse = await buyBitcoin({provider: BuyBitcoinProvider.MOONPAY})
} catch (error) {
console.log(error)
}
```
</section>
<div slot="title">Dart</div>
<section>
```dart
try {
BuyBitcoinResponse buyBitcoinResponse = buyBitcoin(
reqData: BuyBitcoinRequest(provider: BuyBitcoinProvider.Moonpay,
),
);
} catch {
// Handle error
}
```
</section>
<div slot="title">Python</div>
<section>
```python
try:
buy_bitcoin_resp = sdk_services.buy_bitcoin(
breez_sdk.BuyBitcoinRequest(
breez_sdk.BuyBitcoinProvider.MOONPAY))
except Exception as error:
# Handle error
```
</section>
<div slot="title">Go</div>
<section>
```go
buyBitcoinResponse, err := sdkService.BuyBitcoin(breez_sdk.BuyBitcoinRequest{
Provider: breez_sdk.BuyBitcoinProviderMoonpay,
})
```
</section>
<div slot="title">C#</div>
<section>
```cs
try
{
var buyBitcoinResponse = sdk.BuyBitcoin(
new BuyBitcoinRequest(BuyBitcoinProvider.MOONPAY));
}
catch (Exception)
{
// Handle error
}
```
</section>
</custom-tabs>

View File

@@ -3,13 +3,22 @@
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:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
let lsp_id = sdk.lsp_id().await?;
let lsp_info = sdk.lsp_info().await?;
```
</section>
<div slot="title">Swift</div>
<section>
```swift
do {
let lspId = try sdk.lspId()
let lspInfo = try sdk.fetchLspInfo(lspId: lspId!)
let lspInfo = try sdk.lspInfo()
} catch {
// Handle error
}
@@ -19,11 +28,11 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val lspId = sdk.lspId()
if (lspId != null) {
val lspInfo = sdk.fetchLspInfo(lspId)
val lspInfo = sdk.lspInfo()
} else {
// Handle no lsp id scenario
}
@@ -39,7 +48,7 @@ try {
```typescript
try {
const lspId = await lspId()
const lspInfo = await fetchLspInfo(lspId)
const lspInfo = await lspInfo()
} catch (error) {
console.log(error)
}
@@ -65,7 +74,7 @@ try {
```python
try:
lsp_id = sdk_services.lsp_id()
lsp_info = sdk_services.fetch_lsp_info(lsp_id)
lsp_info = sdk_services.lsp_info()
except Exception as error:
# Handle error
@@ -80,7 +89,7 @@ lspId, err := sdkServices.LspId()
if err != nil {
// Handle error
}
lspInfo, err := sdkServices.FetchLspInfo(*lspId)
lspInfo, err := sdkServices.LspInfo()
if err != nil {
// Handle error
}
@@ -94,7 +103,7 @@ if err != nil {
try
{
var lspId = sdk.LspId();
var lspInfo = sdk.FetchLspInfo(lspId!);
var lspInfo = sdk.LspInfo();
}
catch (Exception)
{
@@ -107,6 +116,14 @@ catch (Exception)
When you have selected an LSP you may then connect to it.
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
sdk.connect_lsp(lsp_id).await?;
```
</section>
<div slot="title">Swift</div>
<section>
@@ -122,7 +139,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
sdk.connectLsp(lspId)
} catch (e: Exception) {
@@ -192,4 +209,28 @@ catch (Exception)
}
```
</section>
</custom-tabs>
</custom-tabs>
## Channel Opening Fees
Some Breez SDK operations[^1] may need opening a new channel with the LSP. The SDK supports the LSP2 dynamic fees spec[^2],
which describes how these channel opening fees are handled.
For the client, the key points are:
* The `LspInformation` can be fetched at any point and includes a list of channel opening fees and the duration for which
they are valid. The fees are sorted from cheapest to most expensive. The higher fees are typically also valid for longer.
* Depending on the application and use-case, the client may choose an appropriate fee and give it as an argument in the
relevant Breez SDK method. If this fee argument is not provided, Breez SDK will choose an appropriate one instead.
The channel opening fees are provided in a structure[^3] that includes the conditions associated with these fees, like
the minimum invoice amount or the date and time until when this opening fee is valid.
---
[^1]: See the service methods `receive_payment`, `receive_onchain` or `buy_bitcoin`.
[^2]: [https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS2]()
[^3]: [https://breez.github.io/breez-sdk/breez_sdk_core/struct.OpeningFeeParams.html]()

View File

@@ -6,7 +6,7 @@ In order to list the available fiat currencies:
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val fiatCurrencyList = sdk.listFiatCurrencies()
} catch (e: Exception) {
@@ -81,7 +81,7 @@ To get the current BTC rate for the currencies:
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val fiatRatesMap = sdk.fetchFiatRates()
} catch (e: Exception) {
@@ -158,7 +158,7 @@ At the example project you can see these methods combined:
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
fun fiatCurrenciesAndRate(): Map<FiatCurrency, Rate> = try {
val fiatCurrencies = sdk.listFiatCurrencies()
val fiatRates = sdk.fetchFiatRates()

View File

@@ -96,7 +96,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
// SDK events listener
class SDKListener : EventListener {
override fun onEvent(e: BreezEvent) {
@@ -335,7 +335,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val nodeInfo = sdk.nodeInfo()
val lnBalance = nodeInfo?.channelsBalanceMsat

View File

@@ -54,7 +54,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
// Endpoint can also be of the form:
// keyauth://domain.com/auth?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…

View File

@@ -45,7 +45,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
// Endpoint can also be of the form:
// lnurlp://domain.com/lnurl-pay?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf

View File

@@ -45,7 +45,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
// Endpoint can also be of the form:
// lnurlw://domain.com/lnurl-withdraw?key=val
// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7…
@@ -155,7 +155,6 @@ var lnurlWithdrawUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4exctthd96xserjv9
try
{
var lnurlWithdrawUrl = "";
var input = BreezSdkMethods.ParseInput(lnurlWithdrawUrl);
if (input is InputType.LnUrlWithdraw lnurlw)
{

View File

@@ -10,7 +10,17 @@ Breez SDK automatically connects your node to the LSP peer and you can now recei
<section>
```rust,ignore
let invoice = sdk.receive_payment(3000, "Invoice for 3000 sats".into()).await?;
let res = sdk.receive_payment(
ReceivePaymentRequest {
amount_sats: 3000,
description: "Invoice for 3000 sats".into(),
cltv: None,
expiry: None,
opening_fee_params: None,
preimage: None,
use_description_hash: None
})
.await?;
```
</section>
@@ -19,7 +29,10 @@ let invoice = sdk.receive_payment(3000, "Invoice for 3000 sats".into()).await?;
```swift
do {
let invoice = try sdk.receivePayment(amountSats: 3000, description: "Invoice for 3000 sats")
let invoice = try sdk.receivePayment(
reqData: ReceivePaymentRequest(
amountSats: 3000,
description: "Invoice for 3000 sats"))
} catch {
// handle error
}
@@ -29,7 +42,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val invoice = sdk.receivePayment(3000L.toULong(), "Invoice for 3000 sats")
} catch (e: Exception) {
@@ -43,7 +56,10 @@ try {
```typescript
try {
const invoice = await receivePayment(3000, "Invoice for 3000 sats")
const invoice = await receivePayment({
amountSats: 3000,
description: "Invoice for 3000 sats"
})
} catch (error) {
console.log(error)
}
@@ -55,8 +71,12 @@ try {
```dart
try {
ReceivePaymentRequestData requestData = ReceivePaymentRequestData(amountSats: 3000, description: "Invoice for 3000 sats");
ReceivePaymentResponse invoice = await receivePayment(reqData: requestData);
ReceivePaymentResponse invoice = await receivePayment(
reqData: ReceivePaymentRequestData(
amountSats: 3000,
description: "Invoice for 3000 sats",
),
);
} catch (error) {
// handle error
}
@@ -68,7 +88,10 @@ try {
```python
try:
invoice = sdk_services.receive_payment(3000, "Invoice for 3000 sats")
receive_payment_response = sdk_services.receive_payment(
breez_sdk.ReceivePaymentRequest(
amount_sats=3000,
description="Invoice for 3000 sats"))
except Exception as error:
# Handle error
```
@@ -78,7 +101,10 @@ except Exception as error:
<section>
```go
invoice, err := sdkServices.ReceivePayment(3000, "Invoice for 3000 sats")
invoice, err := sdkService.ReceivePayment(breez_sdk.ReceivePaymentRequest{
AmountSats: 3000,
Description: "Invoice for 3000 sats",
})
```
</section>
@@ -88,7 +114,8 @@ invoice, err := sdkServices.ReceivePayment(3000, "Invoice for 3000 sats")
```cs
try
{
var invoice = sdk.ReceivePayment(3000, "Invoice for 3000 sats");
var invoice = sdk.ReceivePayment(
new ReceivePaymentRequest(3000, "Invoice for 3000 sats"));
}
catch (Exception)
{
@@ -106,7 +133,7 @@ catch (Exception)
```rust,ignore
let bolt11 = "...";
sdk.send_payment(bolt11.into(), Some(3000)).await?;
sdk.send_payment(bolt11.into(), None).await?;
```
</section>
@@ -116,7 +143,9 @@ sdk.send_payment(bolt11.into(), Some(3000)).await?;
```swift
let bolt11 = "...";
do {
let payment = try sdk.sendPayment(bolt11: bolt11, amountSats: 3000)
// The `amountSats` param is optional so nil can be passed if the
// bolt11 invoice spesifies an amount.
let payment = try sdk.sendPayment(bolt11: bolt11, amountSats: 3000)
} catch {
// handle error
}
@@ -126,7 +155,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
val bolt11 = "..."
try {
val payment = sdk.sendPayment(bolt11, 3000L.toULong())
@@ -171,7 +200,9 @@ try {
```python
bolt11 = "..."
try:
sdk_services.send_payment(bolt11, 3000)
# The `amountSats` param is optional so None can be passed if the
# bolt11 invoice spesifies an amount.
sdk_services.send_payment(bolt11=bolt11, amount_sats=None)
except Exception as error:
# Handle error
```
@@ -190,7 +221,7 @@ payment, err := sdkServices.SendPayment(bolt11, 3000)
<section>
```cs
const bolt11 = "...";
var bolt11 = "...";
try
{
var payment = sdk.SendPayment(bolt11, 3000);
@@ -231,7 +262,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
val nodeId = "..."
try {
val payment = sdk.sendSpontaneousPayment(nodeId, 3000L.toULong())
@@ -274,9 +305,9 @@ try {
<section>
```python
let node_id = "..."
node_id = "..."
try:
sdk_services.send_spontaneous_payment(node_id, 3000)
sdk_services.send_spontaneous_payment(node_id=node_id, amount_sats=3000)
except Exception as error:
# Handle error
```
@@ -295,7 +326,7 @@ payment, err := sdkServices.SendSpontaneousPayment(nodeId, 3000)
<section>
```cs
const nodeId = "...";
var nodeId = "...";
try
{
var payment = sdk.SendSpontaneousPayment(nodeId, 3000);

View File

@@ -1,12 +1,18 @@
# Receiving an on-chain transaction (swap-in)
There are cases when you have funds in some bitcoin address and you would like to send those to your lightning node.
In such cases, the SDK might have to open a new channel, for which case you can specify an optional user-selected
channel opening fee[^1]. For simplicity, the examples below use the cheapest fee available.
In order to receive funds you first have to be connected to an [LSP](connecting_lsp.md).
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
let swap_info = sdk.receive_onchain().await?;
let swap_info = sdk.receive_onchain(
ReceiveOnchainRequest { opening_fee_params: None } )
.await?;
// Send your funds to the below bitcoin address
let address = swap_info.bitcoin_address;
@@ -18,7 +24,7 @@ let address = swap_info.bitcoin_address;
```swift
do {
let swapInfo = try sdk.receiveOnchain()
let swapInfo = try sdk.receiveOnchain(req: ReceiveOnchainRequest())
// Send your funds to the bellow bitcoin address
let address = swapInfo.bitcoinAddress;
@@ -31,7 +37,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val swapInfo = sdk.receiveOnchain()
// Send your funds to the bellow bitcoin address
@@ -47,7 +53,7 @@ try {
```typescript
try {
const swapInfo = await receiveOnchain()
const swapInfo = await receiveOnchain({})
// Send your funds to the below bitcoin address
const address = swapInfo.bitcoinAddress;
@@ -62,7 +68,7 @@ try {
```dart
try {
SwapInfo swapInfo = await receiveOnchain();
SwapInfo swapInfo = await receiveOnchain(ReceiveOnchainRequest());
// Send your funds to the below bitcoin address
String address = swapInfo.bitcoinAddress;
@@ -77,7 +83,8 @@ try {
```python
try:
swap_info = sdk_services.receive_onchain()
swap_info = sdk_services.receive_onchain(breez_sdk.ReceiveOnchainRequest())
# Send your funds to the below bitcoin address
address = sdk_services.swap_info.bitcoin_address
except Exception as error:
@@ -89,7 +96,7 @@ except Exception as error:
<section>
```go
if swapInfo, err := sdkServices.ReceiveOnchain(); err != nil {
if swapInfo, err := sdkServices.ReceiveOnchain(breez_sdk.ReceiveOnchainRequest{}); err != nil {
// Send your funds to the below bitcoin address
address := swapInfo.BitcoinAddress
}
@@ -102,7 +109,7 @@ if swapInfo, err := sdkServices.ReceiveOnchain(); err != nil {
```cs
try
{
var swapInfo = sdk.ReceiveOnchain();
var swapInfo = sdk.ReceiveOnchain(new ReceiveOnchainRequest());
// Send your funds to the below bitcoin address
var address = swapInfo.bitcoinAddress;
@@ -141,7 +148,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val swapInfo = sdk.inProgressSwap()
} catch (e: Exception) {
@@ -240,7 +247,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
try {
val refundables = sdk.listRefundables()
} catch (e: Exception) {
@@ -330,9 +337,9 @@ let satPerVbyte = <refund tx fee rate>
do {
try sdk.refund(
swapAddress: "",
toAddress: destinationAddress,
satPerVbyte: satPerVbyte)
swapAddress: refundable?.bitcoinAddress,
toAddress: "...",
satPerVbyte: satPerVbyte)
} catch {
// handle error
}
@@ -342,7 +349,7 @@ do {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
val swapAddress = "..."
val destinationAddress = "..."
val satPerVbyte = 1.toUInt()
@@ -394,7 +401,10 @@ destination_address = "..."
sat_per_vbyte = <refund tx fee rate>
try:
sdk_services.refund(refundable.bitcoin_address, destination_address, sat_per_vbyte)
result = sdk_services.refund(
swap_address=refundable.bitcoin_address,
to_address=to_address,
sat_per_vbyte=sat_per_vbyte)
except Exception as error:
# Handle error
```
@@ -440,13 +450,10 @@ To calculate the fees for a channel being opened by the LSP:
<section>
```rust,ignore
async fn calculate_channel_opening_fee(amount_msat: u64) -> Result<u64> {
let channel_opening_fee_needed = is_channel_opening_fee_needed(amount_msat, sdk.clone())?;
match channel_opening_fee_needed {
true => calculate_fees_for_amount(amount_msat).await,
false => Ok(0),
}
}
let amount_msat = <amount msat>;
let channel_fees = sdk.open_channel_fee(
OpenChannelFeeRequest { amount_msat, expiry: None })
.await?;
```
</section>
@@ -454,12 +461,12 @@ async fn calculate_channel_opening_fee(amount_msat: u64) -> Result<u64> {
<section>
```swift
func calculateChannelOpeningFee(amountMsats: Int64) -> Int64? {
var channelOpeningFeeNeeded = isChannelOpeningFeeNeeded(amountMsats: amountMsats)
if channelOpeningFeeNeeded {
return calculateFeesForAmount(amountMsats: amountMsats)
}
return nil
let amountMsat = <amount msat>
do {
let channelFees = try sdk.openChannelFee(
req: OpenChannelFeeRequest(amountMsat: amountMsat))
} catch {
// Handle error
}
```
</section>
@@ -467,14 +474,8 @@ func calculateChannelOpeningFee(amountMsats: Int64) -> Int64? {
<div slot="title">Android</div>
<section>
```kotlin
fun calculateChannelOpeningFee(amountMsats: Long): Long? {
val channelOpeningFeeNeeded = isChannelOpeningFeeNeeded(amountMsats)
if (channelOpeningFeeNeeded) {
return calculateFeesForAmount(amountMsats)
}
return null
}
```kotlin,ignore
// TODO add example for openChannelFee
```
</section>
@@ -482,12 +483,11 @@ fun calculateChannelOpeningFee(amountMsats: Long): Long? {
<section>
```typescript
const calculateChannelOpeningFee = async (amountMsats: number): number => {
const channelOpeningFeeNeeded = await isChannelOpeningFeeNeeded(amountMsats)
if (channelOpeningFeeNeeded) {
return calculateFeesForAmount(amountMsats)
}
return 0
const amountMsat = <amount msat>
try {
const channelFees = await openChannelFee({amountMsat: amountMsat})
} catch (error) {
// handle error
}
```
</section>
@@ -496,10 +496,15 @@ const calculateChannelOpeningFee = async (amountMsats: number): number => {
<section>
```dart
int calculateChannelOpeningFee(int amountMsat) async {
bool isChannelOpeningFeeNeeded = await isChannelOpeningFeeNeeded(amountMsat);
return isChannelOpeningFeeNeeded ? calculateFeesForAmount(amountMsat) : 0;
}
int amountMsats = <amount msats>
try {
int channelFees = openChannelFee(OpenChannelFeeRequest(
amountMsats: amountMsats,
),
);
} catch {
// Handle error
}
```
</section>
@@ -507,13 +512,13 @@ int calculateChannelOpeningFee(int amountMsat) async {
<section>
```python
def calculate_channel_opening_fees(amount_msats):
is_channel_opening_fee_needed = is_channel_opening_fee_needed()
if is_channel_opening_fee_needed:
return calculate_fees_for_amount(amount_msats)
else:
return None
amount_msat = <amount msats>
try:
channel_fees = sdk_services.open_channel_fee(
breez_sdk.OpenChannelFeeRequest(
amount_msat=amount_msat))
except Exception as error:
# Handle error
```
</section>
@@ -521,13 +526,8 @@ def calculate_channel_opening_fees(amount_msats):
<section>
```go
func CalculateChannelOpeningFee(amountMsats uint64) (uint64, error) {
isChannelOpeningFeeNeeded := isChannelOpeningFeeNeeded(amountMsats)
if !isChannelOpeningFeeNeeded {
return 0, fmt.Errorf("Channel not needed")
}
return calculateFeesForAmount(amountMsats), nil
}
amountMsat := <amount msat>
channelFees, err := sdkServices.OpenChannelFee(breez_sdk.OpenChannelFeeRequest{AmountMsat: amountMsat})
```
</section>
@@ -535,322 +535,14 @@ func CalculateChannelOpeningFee(amountMsats uint64) (uint64, error) {
<section>
```cs
ulong calculateChannelOpeningFee(ulong amountMsats)
{
var channelOpeningFeeNeeded = isChannelOpeningFeeNeeded(amountMsats);
if (channelOpeningFeeNeeded)
{
return calculateFeesForAmount(amountMsats);
}
return 0;
}
ulong amountMsat = <amount msat>;
var channelFees = sdk.OpenChannelFee(new OpenChannelFeeRequest(amountMsat));
```
</section>
</custom-tabs>
How to detect if open channel fees are needed:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
fn is_channel_opening_fee_needed(amount_msats: u64) -> Result<bool> {
let node_info = sdk.node_info()?.ok_or(anyhow!("No node info found"))?;
Ok(node_info.inbound_liquidity_msats <= amount_msats)
}
```
</section>
<div slot="title">Swift</div>
<section>
```swift
func isChannelOpeningFeeNeeded(amountMsats: Int64) -> Bool {
do {
let nodeInfo = try sdk.nodeInfo()
if let inboundLiquidityMsats = nodeInfo?.inboundLiquidityMsats {
return inboundLiquidityMsats <= amountMsats
}
} catch {
// Handle error
}
return false
}
```
</section>
<div slot="title">Android</div>
<section>
```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
}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
const isChannelOpeningFeeNeeded = async (amountMsats: number): boolean => {
try {
const nodeInfo = await nodeInfo()
return nodeInfo.inboundLiquidityMsats <= amountMsats
} catch (error) {
// handle error
}
return false
}
```
</section>
<div slot="title">Dart</div>
<section>
```dart
// Assumes nodeState isn't empty
bool isChannelOpeningFeeNeeded(int amountMsat) async {
NodeState? nodeState = await getNodeState();
return amountMsat >= nodeState.inboundLiquidityMsats;
}
```
</section>
<div slot="title">Python</div>
<section>
```python
def is_channel_opening_fee_needed(amount_msats):
return sdk_services.node_info().inbound_liquidity_msats <= amount_msats
```
</section>
<div slot="title">Go</div>
<section>
```go
func isChannelOpeningFeeNeeded(amountMsats uint64) bool {
nodeInfo, err := sdkServices.NodeInfo()
if err != nil {
// Handle error
}
return nodeInfo.InboundLiquidityMsats <= amountMsats
}
```
</section>
<div slot="title">C#</div>
<section>
```cs
bool isChannelOpeningFeeNeeded(ulong amountMsats)
{
try
{
var nodeInfo = sdk.NodeInfo();
return nodeInfo.inboundLiquidityMsats <= amountMsats;
}
catch (Exception)
{
// handle error
}
return false;
}
```
</section>
</custom-tabs>
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:
<custom-tabs category="lang">
<div slot="title">Rust</div>
<section>
```rust,ignore
async fn calculate_fees_for_amount(amount_msat: u64) -> Result<u64> {
let lsp_id = sdk.lsp_id().await?.ok_or(anyhow!("No lsp id found"))?;
let lsp_info = sdk
.fetch_lsp_info(lsp_id)
.await?
.ok_or(anyhow!("No lsp id found"))?;
// We calculate the dynamic fees in millisatoshis rounded to satoshis.
let channel_dynamic_fee_msat =
amount_msat * lsp_info.channel_fee_permyriad as u64 / 10_000 / 1000 * 1000;
let fee_msat = max(
lsp_info.channel_minimum_fee_msat as u64,
channel_dynamic_fee_msat,
)
Ok(fee_msat)
}
```
</section>
<div slot="title">Swift</div>
<section>
```swift
func calculateFeesForAmount(amountMsats: Int64) -> Int64? {
do {
if let lspId = try sdk.lspId() {
let lspInfo = try sdk.fetchLspInfo(lspId: lspId)
// We calculate the dynamic fees in millisatoshis rounded to satoshis.
let channelDynamicFeeMsat = amountMsats * lspInfo!.channelFeePermyriad / 10_000 / 1000 * 1000
let feeMsat = max(lspInfo!.channelMinimumFeeMsat, channelDynamicFeeMsat)
return feeMsat
}
} catch {
// Handle error
}
return nil
}
```
</section>
<div slot="title">Android</div>
<section>
```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
}
```
</section>
<div slot="title">React Native</div>
<section>
```typescript
const calculateFeesForAmount = async (amountMsats: number): number => {
try {
const id = await lspId()
const lspInfo = await fetchLspInfo(id)
// We calculate the dynamic fees in millisatoshis rounded to satoshis.
const channelDynamicFeeMsat = amountMsats * lspInfo.channelFeePermyriad / 10000 / 1000 * 1000
const feeMsat = Math.max(lspInfo.channelMinimumFeeMsat, channelDynamicFeeMsat)
return feeMsat
} catch (error) {
// handle error
}
return 0
}
```
</section>
<div slot="title">Dart</div>
<section>
```dart
// Assumes lspId & lspInformation isn't empty
int calculateFeesForAmount(int amountMsat) async {
String? lspId = await getLspId();
LSPInformation? lspInformation = await fetchLspInfo(lspId);
// We calculate the dynamic fees in millisatoshis rounded to satoshis.
int channelFeesMsat = (amountMsat * lspInformation.channelFeePermyriad / 10000 / 1000 * 1000);
return max(channelFeesMsat, lspInformation.channelMinimumFeeMsat);
}
```
</section>
<div slot="title">Python</div>
<section>
```python
def calculate_fees_for_amount(amount_msats):
# We need to open channel so we are calculating the fees for the LSP.
lsp_id = sdk_services.lsp_id()
lsp_info = sdk_services.fetch_lsp_info()
# We calculate the dynamic fees in millisatoshis rounded to satoshis.
channel_dynamic_fee = amount_msats * lsp_info.channel_minimum_fee_msat * lsp_info.channel_fee_permyriad / 10000 // 10000 * 10000
fee_msat = max(lsp_info.channel_minimum_fee_msat, channel_dynamic_fee)
return fee_msat
```
</section>
<div slot="title">Go</div>
<section>
```go
func calculateFeesForAmount(amountMsats uint64) uint64 {
lspId, err := sdkServices.LspId()
if err != nil {
// Handle error
}
lspInfo, err := sdkServices.FetchLspInfo(*lspId)
if err != nil {
// Handle error
}
// We calculate the dynamic fees in millisatoshis rounded to satoshis
channelDynamicFeeMsats := amountMsats * uint64(lspInfo.ChannelFeePermyriad) / 10000 / 1000 * 1000
feeMsats := uint64(lspInfo.ChannelMinimumFeeMsat)
if channelDynamicFeeMsats >= feeMsats {
feeMsats = channelDynamicFeeMsats
}
return feeMsats
}
```
</section>
<div slot="title">C#</div>
<section>
```cs
ulong calculateFeesForAmount(ulong amountMsats)
{
try
{
var id = sdk.LspId();
var lspInfo = sdk.FetchLspInfo(id);
// We calculate the dynamic fees in millisatoshis rounded to satoshis.
var channelDynamicFeeMsat = amountMsats * (ulong)lspInfo.channelFeePermyriad / 10000 / 1000 * 1000;
var feeMsat = Math.Max((ulong)lspInfo.channelMinimumFeeMsat, channelDynamicFeeMsat);
return feeMsat;
}
catch (Exception)
{
// Handle error
}
return 0;
}
```
</section>
</custom-tabs>
[^1]: For more details on these fees, see [Channel Opening Fees](connecting_lsp.md#channel-opening-fees)

View File

@@ -9,11 +9,13 @@ First, fetch the current reverse swap fees:
<section>
```rust,ignore
let current_fees = sdk.fetch_reverse_swap_fees().await?;
let current_fees = sdk.fetch_reverse_swap_fees(
ReverseSwapFeesRequest {
send_amount_sat: Some(50000),
})
.await?;
info!("Percentage fee for the reverse swap service: {}", current_fees.fees_percentage);
info!("Estimated miner fees in sats for locking up funds: {}", current_fees.fees_lockup);
info!("Estimated miner fees in sats for claiming funds: {}", current_fees.fees_claim);
info!("Total estimated fees for reverse swap: {}", current_fees.total_estimated_fees);
```
</section>
@@ -21,12 +23,11 @@ info!("Estimated miner fees in sats for claiming funds: {}", current_fees.fees_c
<section>
```swift
let sendAmountSat:UInt64? = 50000
try {
let currentFees = try sdk.fetchReverseSwapFees()
println("Percentage fee for the reverse swap service: \(currentFees.feesPercentage)")
println("Estimated miner fees in sats for locking up funds: \(currentFees.feesLockup)")
println("Estimated miner fees in sats for claiming funds: \(currentFees.feesClaim)")
let currentFees = try sdk.fetchReverseSwapFees(
req: ReverseSwapFeesRequest(sendAmountSat: sendAmountSat))
print("Total estimated fees for reverse swap: \(currentFees.totalEstimatedFees)")
} catch {
// handle error
}
@@ -36,12 +37,10 @@ try {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
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}")
val fees = sdk.fetchReverseSwapFees(ReverseSwapFeesRequest(50000))
Log.v("Breez", "Total estimated fees for reverse swap: ${fees.totalEstimatedFees}")
} catch (e: Exception) {
// handle error
}
@@ -53,11 +52,9 @@ try {
```typescript
try {
const currentFees = await fetchReverseSwapFees()
const currentFees = await fetchReverseSwapFees({sendAmountSat: 50000})
console.log(`Percentage fee for the reverse swap service: ${currentFees.feesPercentage}`);
console.log(`Estimated miner fees in sats for locking up funds: ${currentFees.feesLockup}`);
console.log(`Estimated miner fees in sats for claiming funds: ${currentFees.feesClaim}`);
console.log(`Total estimated fees for reverse swap: ${currentFees.totalEstimatedFees}`);
} catch (error) {
console.log(error)
}
@@ -69,11 +66,13 @@ try {
```dart
try {
ReverseSwapPairInfo currentFees = await fetchReverseSwapFees();
ReverseSwapPairInfo currentFees = await fetchReverseSwapFees(
req: ReverseSwapFeesRequest(
sendAmountSat: 50000,
),
);
print(`Percentage fee for the reverse swap service: ${currentFees.feesPercentage}`);
print(`Estimated miner fees in sats for locking up funds: ${currentFees.feesLockup}`);
print(`Estimated miner fees in sats for claiming funds: ${currentFees.feesClaim}`);
print("Total estimated fees for reverse swap: ${currentFees.totalEstimatedFees}");
} catch (error) {
// handle error
}
@@ -85,10 +84,9 @@ try {
```python
try:
current_fees = sdk_services.fetch_reverse_swap_fees()
print("Percentage fee for the reverse swap service: ", current_fees.fees_percentage)
print("Estimated miner fees in sats for locking up funds: ", current_fees.fees_lockup)
print("Estimated miner fees in sats for claiming funds: ", current_fees.fees_claim)
current_fees = sdk_services.fetch_reverse_swap_fees(
breez_sdk.ReverseSwapFeesRequest(send_amount_sat=50000))
print("Total estimated fees for reverseswap:", current_fees.total_estimated_fees)
except Exception as error:
# Handle error
```
@@ -98,10 +96,12 @@ except Exception as error:
<section>
```go
if currentFees, err := sdkServices.FetchReverseSwapFees(); err != nil {
log.Printf("Percentage fee for the reverse swap service: %v", currentFees.FeesPercentage)
log.Printf("Estimated miner fees in sats for locking up funds: %v", currentFees.FeesLockup)
log.Printf("Estimated miner fees in sats for claiming funds: %v", currentFees.FeesClaim)
sendAmountSat := uint64(50000)
reverseSwapFeesRequest := breez_sdk.ReverseSwapFeesRequest{
SendAmountSat: &sendAmountSat,
}
if currentFees, err := sdkService.FetchReverseSwapFees(reverseSwapFeesRequest); err != nil {
log.Printf("Total estimated fees for reverse swap: %v", currentFees.TotalEstimatedFees)
}
```
</section>
@@ -112,10 +112,9 @@ if currentFees, err := sdkServices.FetchReverseSwapFees(); err != nil {
```cs
try
{
var currentFees = sdk.FetchReverseSwapFees();
Console.WriteLine($"Percentage fee for the reverse swap service: {currentFees.feesPercentage}");
Console.WriteLine($"Estimated miner fees in sats for locking up funds: {currentFees.feesLockup}");
Console.WriteLine($"Estimated miner fees in sats for claiming funds: {currentFees.feesClaim}");
var currentFees = sdk.FetchReverseSwapFees(
new ReverseSwapFeesRequest(50000));
Console.WriteLine($"Total estimated fees for reverse swap: {currentFees.totalEstimatedFees}");
}
catch (Exception)
{
@@ -153,7 +152,7 @@ println("Maximum amount, in sats: \(current_fees.max)")
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
Log.v("Breez", "Minimum amount, in sats: ${fees.min}")
Log.v("Breez", "Maximum amount, in sats: ${fees.max}")
```
@@ -172,8 +171,8 @@ console.log(`Maximum amount, in sats: ${currentFees.max}`);
<section>
```dart
print(`Minimum amount, in sats: ${currentFees.min}`);
print(`Maximum amount, in sats: ${currentFees.max}`);
print("Minimum amount, in sats: ${currentFees.min}");
print("Maximum amount, in sats: ${currentFees.max}");
```
</section>
@@ -214,8 +213,9 @@ Once you checked the fees are acceptable, you can start the reverse swap:
```rust,ignore
let destination_address = String::from("bc1..");
let amount_sat = current_fees.min;
let satPerVbyte = <fee rate>;
sdk.send_onchain(amount_sat, destination_address, current_fees.fees_hash).await?;
sdk.send_onchain(amount_sat, destination_address, current_fees.fees_hash, satPerVbyte).await?;
```
</section>
@@ -227,7 +227,11 @@ let destinationAddress = "bc1.."
let amountSat = currentFees.min
let satPerVbyte = <fee rate>
try {
try sdk.sendOnchain(amountSat: amountSat, onchainRecipientAddress: destinationAddress, pairHash: currentFees.feesHash, satPerVbyte: satPerVbyte)
try sdk.sendOnchain(
amountSat: amountSat,
onchainRecipientAddress: destinationAddress,
pairHash: currentFees.feesHash,
satPerVbyte: satPerVbyte)
} catch {
// handle error
}
@@ -237,7 +241,7 @@ try {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
val address = "bc1.."
val amountSat = 123L.toULong()
val satPerVbyte = 1L.toULong()
@@ -269,7 +273,7 @@ try {
```dart
String destinationAddress = "bc1..";
int amountSat = currentFees.min;
int amountSat = <amount>;
int satPerVbyte = <fee rate>
try {
ReverseSwapInfo reverseSwapInfo = await sendOnchain(
@@ -290,9 +294,15 @@ try {
```python
destination_address = "bc1.."
amount_sat = current_fees.min
fee_hash = current_fees.fee_hash
sat_per_vbyte = <fee rate>
try:
sdk.send_onchain(amount_sat, destination_address, current_fees.fees_hash)
sdk_services.send_onchain(
amount_sat=amount_msats,
onchain_recipient_address="...",
pair_hash=current_fees.fee_hash,
sat_per_vbyte=sat_per_vbyte)
except Exception as error:
# Handle erorr
```
@@ -319,7 +329,8 @@ var amountSat = currentFees.min;
var satPerVbyte = <fee rate>;
try
{
var reverseSwapInfo = sdk.SendOnchain(amountSat, destinationAddress, currentFees.feesHash, satPerVbyte);
var reverseSwapInfo = sdk.SendOnchain(
amountSat, destinationAddress, currentFees.feesHash, satPerVbyte);
}
catch (Exception)
{
@@ -359,7 +370,7 @@ for rs in sdk.inProgressReverseSwaps() {
<div slot="title">Android</div>
<section>
```kotlin
```kotlin,ignore
for (rs in sdk.inProgressReverseSwaps()) {
Log.v("Breez", "Reverse swap ${rs.id} in progress, status is ${rs.status}")
}
@@ -435,7 +446,7 @@ try
catch (Exception)
{
// Handle error
}
}
```
</section>
</custom-tabs>