diff --git a/README.md b/README.md
index 47f9969..adaadd7 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,14 @@ The SDK docs are live at [https://sdk-doc.breez.technology](https://sdk-doc.bree
## Contributions
-For syntax and supported features, see [https://rust-lang.github.io/mdBook](https://rust-lang.github.io/mdBook).
\ No newline at end of file
+For syntax and supported features, see [https://rust-lang.github.io/mdBook](https://rust-lang.github.io/mdBook).
+
+## Develop
+
+To locally serve the docs run:
+
+```bash
+cargo install mdbook
+mdbook build
+mdbook serve
+```
diff --git a/src/guide/getting_started.md b/src/guide/getting_started.md
index 0ee470b..5ff25bc 100644
--- a/src/guide/getting_started.md
+++ b/src/guide/getting_started.md
@@ -9,7 +9,7 @@ The Breez SDK provides the following services:
* Fetching node status (e.g. balance, max allow to pay, max allow to receive, on-chain balance, etc.)
* Connecting to a new or existing node.
-Connecting to a node requires a seed (your master key) and credentials. The seed is a bip39 mnemonic and the credentials are retrieved by registering a new node or recovering an existing one.
+Connecting to a node requires a seed (your master key). The seed is a bip39 mnemonic.
## Installing
@@ -19,44 +19,30 @@ Breez SDK is available in several platforms. Follow the [Installing](install.md)
Rust
-The first step is to register a new node. In order to do that a seed is needed.
-## Registering a new node
-```rust,no_run
-let seed = ;
-let invite_code = ;
-
-// register_node takes either greenlight credentials (certifate & key) or invite code.
-// At this example we are using the invite code option.
-let credentials = BreezServices::register_node(Network::Bitcoin, seed, None, Some(invite_code)).await?;
-```
-
-## Recovering an existing node
-```rust,no_run
-let seed = ;
-let credentials = BreezServices::recover_node(Network::Bitcoin, seed).await?;
-```
-
-Once the credentials are retrieved they should be saved in a secured storage.
-The next step is to initialize the SDK and start the node:
-
-## Initializing the SDK
+## Connecting
```rust,no_run
// Create the default config
-let mut config = BreezServices::default_config(EnvironmentType::Production);
+let config = BreezServices::default_config(
+ EnvironmentType::Production,
+ "your API key".into(),
+ breez_sdk_core::NodeConfig::Greenlight {
+ config: GreenlightNodeConfig {
+ partner_credentials: None,
+ invite_code: None,
+ },
+ },
+);
// Customize the config object according to your needs
-config.api_key = Some("your API key".into());
config.working_dir = "path to an existing directory".into();
-let sdk = BreezServices::init_services(
+// Connect to the Breez SDK make it ready for use
+let sdk = BreezServices::connect(
config,
- seed.to_vec(),
- credentials.clone(),
+ seed.to_vec(),
Box::new(AppEventListener {}),
)
.await?;
-
-BreezServices::start(rt(), &sdk).await?;
```
At any point we can fetch our balance from the Greenlight node:
@@ -71,35 +57,7 @@ if let Some(node_state) = sdk.node_info()? {
Swift
-The first step is to register a new node
-## Registering a new node
-```swift
-do {
- let seed = try mnemonicToSeed(phrase: "")
- let inviteCode = ""
-
- // register_node takes either greenlight credentials (certifate & key) or invite code.
- // At this example we are using the invite code option.
- let credentials = try registerNode(network: Network.bitcoin, seed: seed, registerCredentials: nil, inviteCode: inviteCode)
-} catch {
- // handle error
-}
-```
-
-## Recovering an existing node
-```swift
-do {
- let seed = try mnemonicToSeed(phrase: "")
- let credentials = try recoverNode(network: Network.bitcoin, seed: seed)
-} catch {
- // handle error
-}
-```
-
-Once the credentials are retrieved they should be saved in a secured storage.
-The next step is to initialize the SDK and start the node:
-
-## Initializing the SDK
+## Connecting
```swift
// SDK events listener
@@ -110,15 +68,18 @@ class SDKListener: EventListener {
}
// Create the default config
-var config = defaultConfig(envType: EnvironmentType.production)
+let seed = try mnemonicToSeed(phrase: "")
+let inviteCode = "your invite code"
+let config = breez_sdk.defaultConfig(envType: EnvironmentType.production, apiKey: "",
+ nodeConfig: NodeConfig.greenlight(
+ config: GreenlightNodeConfig(partnerCredentials: nil,inviteCode: inviteCode)));
// Customize the config object according to your needs
-config.apiKey = "your API key";
-config.workingDir = "path to an existing directory";
+config.workingDir = "path to an existing directory"
-do {
- let sdk = try initServices(config: config, seed: seed, creds: credentials, listener: SDKListener());
- try sdk.start();
+do {
+ // Connect to the Breez SDK make it ready for use
+ let sdk = try connect(config: config, seed: seed, listener: SDKListener());
} catch{
// handle error
}
@@ -140,31 +101,7 @@ do {
React Native
-The first step is to register a new node
-## Registering a new node
-```typescript
-try {
- const seed = await mnemonicToSeed("");
- const inviteCode = "";
-
- // register_node takes either greenlight credentials (certifate & key) or invite code.
- // At this example we are using the invite code option.
- const credentials = await registerNode(Network.BITCOIN, seed, null, inviteCode);
-} catch (error) {
- console.log(error)
-}
-```
-
-## Recovering an existing node
-```typescript
- const seed = await mnemonicToSeed("");
- const credentials = await recoverNode(Network.BITCOIN, seed);
-```
-
-Once the credentials are retrieved they should be saved in a secured storage.
-The next step is to initialize the SDK and start the node:
-
-## Initializing the SDK
+## Connecting
```typescript
// SDK events listener
@@ -173,15 +110,22 @@ addEventListener((type, data) => {
})
// Create the default config
-let config = defaultConfig(EnvironmentType.PRODUCTION)
+const seed = await mnemonicToSeed("");
+const inviteCode = "";
+const nodeConfig : NodeConfig = {
+ type: NodeConfigType.GREENLIGHT,
+ config: {
+ inviteCode: "your invite code"
+ }
+}
+let config = defaultConfig(EnvironmentType.PRODUCTION, "api key", nodeConfig);
// Customize the config object according to your needs
-config.apiKey = "your API key";
config.workingDir = "path to an existing directory";
try {
- const sdkServices = await initServices(config, credentials.deviceKey, credentials.deviceCert, seed);
- await start();
+ // Connect to the Breez SDK make it ready for use
+ const sdkServices = await connect(config, seed);
} catch (error) {
console.log(error);
}
@@ -199,32 +143,90 @@ try {
}
```
+Dart
+
+
+## Connecting
+```dart
+// SDK events listener
+breezEventsStream().listen((event) {
+ print("Received Breez event: $event");
+}
+
+// SDK logs listener
+breezLogStream().listen((log) {
+ print("Received Breez log entry: $log");
+}
+
+// Create the default config
+Uint8List seed = await mnemonicToSeed(phrase: "");
+String inviteCode = "";
+NodeConfg nodeConfig = NodeConfig.greenlight(config: GreenlightNodeConfig(partnerCredentials: null, inviteCode: inviteCode));
+Config config = await defaultConfig(configType: EnvironmentType.Production, apiKey: "", nodeConfig: 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
+ await connect(config: config, seed: seed);
+} catch (error) {
+ // handle error
+}
+```
+At any point we can fetch our balance from the Greenlight node:
+
+```dart
+try {
+ NodeState? nodeInfo = await nodeInfo();
+ int lnBalance = nodeInfo?.channelsBalanceMsat;
+ int onchainBalance = nodeInfo?.onchainBalanceMsat;
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+## Connecting
+```python
+# SDK events listener
+class SDKListener(breez_sdk.EventListener):
+ def on_event(self, event):
+ print(event)
+
+# Create the default config
+seed = mnemonic_to_seed("")
+invite_code = ""
+config = breez_sdk.default_config(breez_sdk.EnvironmentType.PRODUCTION, "api key",
+ breez_sdk.NodeConfig.GREENLIGHT(breez_sdk.GreenlightNodeConfig(None, invite_code)))
+
+# Customize the config object according to your needs
+config.working_dir = "path to an existing directory"
+
+try:
+ # Connect to the Breez SDK make it ready for use
+ sdk_services = breez_sdk.connect(config, seed, SDKListener())
+except Exception as error:
+ # Handle error
+```
+
+At any point we can fetch our balance from the Greenlight node:
+
+```python
+try:
+ node_info = node_info()
+ ln_balance = node_info.channels_balance_msat
+ onchain_balance = node_info.onchain_balance_msat
+except Exception as error:
+ # Handle error
+```
+
Go
-The first step is to register a new node
-## Registering a new node
-```go
-if seed, err := breez_sdk.MnemonicToSeed(""); err != nil {
- inviteCode := ""
-
- // register_node takes either greenlight credentials (certifate & key) or invite code.
- // At this example we are using the invite code option.
- credentials, err := breez_sdk.RegisterNode(breez_sdk.NetworkBitcoin, seed, nil, &inviteCode)
-}
-```
-
-## Recovering an existing node
-```go
-if seed, err := breez_sdk.MnemonicToSeed(""); err != nil {
- credentials := breez_sdk.RecoverNode(Network.BITCOIN, seed)
-}
-```
-
-Once the credentials are retrieved they should be saved in a secured storage.
-The next step is to initialize the SDK and start the node:
-
-## Initializing the SDK
+## Connecting
```go
// SDK events listener
type BreezListener struct{}
@@ -234,17 +236,24 @@ func (BreezListener) OnEvent(e breez_sdk.BreezEvent) {
}
// Create the default config
-config := breez_sdk.DefaultConfig(breez_sdk.EnvironmentTypeProduction)
+apiKey := ""
+inviteCode := ""
+nodeConfig := breez_sdk.NodeConfigGreenlight{
+ Config: breez_sdk.GreenlightNodeConfig{
+ PartnerCredentials: nil,
+ InviteCode: &inviteCode,
+ },
+}
+
+config := breez_sdk.DefaultConfig(breez_sdk.EnvironmentTypeProduction, apiKey, nodeConfig)
// Customize the config object according to your needs
-config.apiKey = "your API key"
config.workingDir = "path to an existing directory"
-if sdkServices, err := breez_sdk.InitServices(config, seed, credentials, BreezListener{}); err != nil {
+if sdkServices, err := breez_sdk.Connect(config, seed, BreezListener{}); err != nil {
sdkServices.Start()
}
```
-
At any point we can fetch our balance from the Greenlight node:
```go
diff --git a/src/guide/install.md b/src/guide/install.md
index 3006644..559bb04 100644
--- a/src/guide/install.md
+++ b/src/guide/install.md
@@ -8,7 +8,7 @@ We recommend integrating the Breez SDK as Gradle dependency from [our Maven repo
To do so, add the following to your Gradle dependencies:
-``` groovy
+```gradle
repositories {
maven {
url("https://mvn.breez.technology/releases")
@@ -50,4 +50,16 @@ Currently c# is built from source only. Please visit the [sdk-bindings](https://
## rust
-Currently rust is still not accessible via cargo and is needed to be built from source. Please visit the [sdk-core](https://github.com/breez/breez-sdk/tree/main/libs/sdk-core) project for instructions.
\ No newline at end of file
+Currently rust is still not accessible via cargo and is needed to be built from source. Please visit the [sdk-core](https://github.com/breez/breez-sdk/tree/main/libs/sdk-core) project for instructions.
+
+## Dart/Flutter
+Currently Dart is built from source only. Please visit the [sdk-flutter](https://github.com/breez/breez-sdk/tree/main/libs/sdk-flutter#readme) project for instructions. We're planning to publish this package to [pub.dev](https://pub.dev/), until then it needs to be specified as a local directory dependency.
+
+```yaml
+dependencies:
+ breez_sdk:
+ path: /breez-sdk/libs/sdk-flutter
+```
+## Python
+
+Currently python is not acceable as a package and is needed to build it from soruce. Please visit [sdk-core](https://github.com/breez/breez-sdk/tree/main/libs/sdk-bindings#python) project for instructions.
diff --git a/src/guide/lnurl_auth.md b/src/guide/lnurl_auth.md
index f89e743..bcb90ef 100644
--- a/src/guide/lnurl_auth.md
+++ b/src/guide/lnurl_auth.md
@@ -73,6 +73,51 @@ try {
}
```
+
+Dart
+
+
+```dart
+// Endpoint can also be of the form:
+// keyauth://domain.com/auth?key=val
+String lnurlAuthUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttvdankjm3lw3skw0tvdankjm3xdvcn6vtp8q6n2dfsx5mrjwtrxdjnqvtzv56rzcnyv3jrxv3sxqmkyenrvv6kve3exv6nqdtyv43nqcmzvdsnvdrzx33rsenxx5unqc3cxgeqgntfgu";
+
+try {
+ InputType inputType = await parse(s: lnurlAuthUrl);
+ if (inputType is InputType_LnUrlAuth) {
+ LnUrlCallbackStatus result = await lnurlAuth(reqData: inputType.data);
+ if (result is LnUrlCallbackStatus_Ok) {
+ print("Successfully authenticated");
+ } else {
+ print("Failed to authenticate");
+ }
+ }
+} catch (error) {
+ // handle error
+}
+```
+
+
+Python
+
+
+```python
+# Endpoint can also be of the form:
+# keyauth://domain.com/auth?key=val
+lnurlAuthUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttvdankjm3lw3skw0tvdankjm3xdvcn6vtp8q6n2dfsx5mrjwtrxdjnqvtzv56rzcnyv3jrxv3sxqmkyenrvv6kve3exv6nqdtyv43nqcmzvdsnvdrzx33rsenxx5unqc3cxgeqgntfgu"
+
+try:
+ parsed_input = breez_sdk.parse_input(lnurl_auth_url)
+ if isinstance(parsed_input, breez_sdk.InputType.LN_URL_AUTH):
+ result = sdk_services.lnurl_auth(parsed_input.data)
+ if result.is_ok():
+ print("Successfully authenticated")
+ else:
+ print("Failed to authenticate")
+except Exception as error:
+ # Handle error
+```
+
Go
@@ -93,11 +138,9 @@ if input, err := breez_sdk.ParseInput(lnurlAuthUrl); err != nil {
}
}
}
-}
```
-
-
+
## Supported Specs
diff --git a/src/guide/lnurl_pay.md b/src/guide/lnurl_pay.md
index acadc65..75cd867 100644
--- a/src/guide/lnurl_pay.md
+++ b/src/guide/lnurl_pay.md
@@ -61,6 +61,48 @@ try {
}
```
+Dart
+
+
+```dart
+// Endpoint can also be of the form:
+// lnurlp://domain.com/lnurl-pay?key=val
+// lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
+String lnurlPayUrl = "lightning@address.com";
+
+try {
+ InputType inputType = await parseInput(s: lnurlPayUrl);
+ if (inputType is InputType_LnUrlPay) {
+ int amountSats = inputType.data.minSendable;
+ LnUrlCallbackStatus result = await lnurlPay(
+ reqData: inputType.data,
+ userAmountSat: amountSats,
+ comment: "comment",
+ );
+ }
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+```python
+# Endpoint can also be of the form:
+# lnurlp://domain.com/lnurl-pay?key=val
+# lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4excttsv9un7um9wdekjmmw84jxywf5x43rvv35xgmr2enrxanr2cfcvsmnwe3jxcukvde48qukgdec89snwde3vfjxvepjxpjnjvtpxd3kvdnxx5crxwpjvyunsephsz36jf
+lnurl_pay_url = "lightning@address.com"
+
+try:
+ parsed_input = breez_sdk.parse_input(lnurl_pay_url)
+ if isinstance(parsed_input, breez_sdk.InputType.LN_URL_PAY):
+ amount_sats = parsed_input.data.min_sendable
+ result = sdk_service.pay_lnurl(parsed_input.data, amount_sats, "comment")
+except Exception as error:
+ # Handle error
+```
+
Go
@@ -83,7 +125,6 @@ if input, err := breez_sdk.ParseInput(lnurlPayUrl); err != nil {
## Supported Specs
-
- [LUD-01](https://github.com/lnurl/luds/blob/luds/01.md) LNURL bech32 encoding
- [LUD-06](https://github.com/lnurl/luds/blob/luds/06.md) `payRequest` spec
- [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) LN Address
diff --git a/src/guide/lnurl_withdraw.md b/src/guide/lnurl_withdraw.md
index 84b8eb7..c3fbe79 100644
--- a/src/guide/lnurl_withdraw.md
+++ b/src/guide/lnurl_withdraw.md
@@ -61,6 +61,46 @@ try {
}
```
+Dart
+
+
+```dart
+// Endpoint can also be of the form:
+// lnurlw://domain.com/lnurl-withdraw?key=val
+String lnurlWithdrawUrl = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4exctthd96xserjv9mn7um9wdekjmmw843xxwpexdnxzen9vgunsvfexq6rvdecx93rgdmyxcuxverrvcursenpxvukzv3c8qunsdecx33nzwpnvg6ryc3hv93nzvecxgcxgwp3h33lxk";
+
+try {
+ InputType inputType = await parseInput(s: lnurlWithdrawUrl);
+ if (inputType is InputType_LnUrlWithdraw) {
+ int amountSats = inputType.data.minWithdrawable;
+ LnUrlCallbackStatus result = await lnurlWithdraw(
+ reqData: inputType.data,
+ amountSats: amountSats,
+ description: "comment",
+ );
+ }
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+```python
+# Endpoint can also be of the form:
+# lnurlw://domain.com/lnurl-withdraw?key=val
+lnurl_withdraw_url = "lnurl1dp68gurn8ghj7mr0vdskc6r0wd6z7mrww4exctthd96xserjv9mn7um9wdekjmmw843xxwpexdnxzen9vgunsvfexq6rvdecx93rgdmyxcuxverrvcursenpxvukzv3c8qunsdecx33nzwpnvg6ryc3hv93nzvecxgcxgwp3h33lxk"
+
+try:
+ parsed_input = parse_input(lnurl_withdraw_url)
+ if isinstance(parsed_input, breez_sdk.InputType.LN_URL_WITHDRAW):
+ amount_sats = parsed_input.data.min_withdrawable
+ result = sdk_services.withdraw_lnurl(parsed_input.data, amount_sats, "comment")
+except Exception as error:
+ # Handle error
+```
+
Go
diff --git a/src/guide/payments.md b/src/guide/payments.md
index f5da6e7..39dde1e 100644
--- a/src/guide/payments.md
+++ b/src/guide/payments.md
@@ -94,6 +94,81 @@ try {
console.log(error)
}
```
+
+Dart
+
+
+## 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:
+
+```dart
+try {
+ ReceivePaymentRequestData requestData = ReceivePaymentRequestData(amountSats: 3000, description: "Invoice for 3000 sats");
+ ReceivePaymentResponse invoice = await receivePayment(reqData: requestData);
+} catch (error) {
+ // handle error
+}
+```
+
+## Sending Lightning Payments
+```dart
+String bolt11 = "...";
+try {
+ Payment payment = await sendPayment(
+ bolt11: bolt11,
+ amountSats: 3000,
+ );
+} catch (error) {
+ // handle error
+}
+```
+
+## Sending Spontaneous Lightning Payments
+```dart
+String nodeId = "...";
+try {
+ Payment payment = await sendSpontaneousPayment(
+ nodeId: nodeId,
+ amountSats: 3000,
+ );
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+## 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:
+
+```python
+try:
+ invoice = sdk_services.receive_payment(3000, "Invoice for 3000 sats")
+except Exception as error:
+ # Handle error
+```
+
+## Sending Lightning Payments
+```python
+bolt11 = "..."
+try:
+ sdk_services.send_payment(bolt11, 3000)
+except Exception as error:
+ # Handle error
+```
+
+## Sending Spontaneous Lightning Payments
+```python
+let node_id = "..."
+try:
+ sdk_services.send_spontaneous_payment(node_id, 3000)
+except Exception as error:
+ # Handle error
+```
+
Go
@@ -117,5 +192,6 @@ payment, err := sdkServices.SendPayment(bolt11, 3000)
const nodeId = "...";
payment, err := sdkServices.SendSpontaneousPayment(nodeId, 3000)
```
+
\ No newline at end of file
diff --git a/src/guide/receive_onchain.md b/src/guide/receive_onchain.md
index a8f167a..1adea6a 100644
--- a/src/guide/receive_onchain.md
+++ b/src/guide/receive_onchain.md
@@ -29,7 +29,7 @@ In order to execute a refund, you need to supply an on-chain address to where th
let refundables = sdk.list_refundables().await?
```
-Once you have a refundable swap in hand, use the follwing code to execute a refund:
+Once you have a refundable swap in hand, use the following code to execute a refund:
```rust,no_run
let destination_address = "...".into()
@@ -76,7 +76,7 @@ do {
}
```
-Once you have a refundable swap in hand, use the follwing code to execute a refund:
+Once you have a refundable swap in hand, use the following code to execute a refund:
```swift
let destinationAddress = "..."
@@ -131,7 +131,7 @@ try {
}
```
-Once you have a refundable swap in hand, use the follwing code to execute a refund:
+Once you have a refundable swap in hand, use the following code to execute a refund:
```typescript
const destinationAddress = "..."
@@ -143,6 +143,109 @@ try {
}
```
+Dart
+
+
+```dart
+try {
+ SwapInfo swapInfo = await receiveOnchain();
+
+ // Send your funds to the below bitcoin address
+ String address = swapInfo.bitcoinAddress;
+} catch (error) {
+ // 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:
+
+```dart
+try {
+ SwapInfo? swapInfo = await inProgressSwap()
+} catch (error) {
+ // 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:
+
+```dart
+try {
+ List refundables = await listRefundables()
+} catch (error) {
+ // handle error
+}
+```
+
+Once you have a refundable swap in hand, use the following code to execute a refund:
+
+```dart
+String destinationAddress = "..."
+int satPerVbyte =
+try {
+ String result = await refund(
+ swapAddress: refundable.bitcoinAddress,
+ toAddress: destinationAddress,
+ satPerVbyte: satPerVbyte,
+ );
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+```python
+try:
+ swap_info = sdk_services.receive_onchain()
+ # Send your funds to the below bitcoin address
+ address = sdk_services.swap_info.bitcoin_address
+except Exception as error:
+ # 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:
+
+```python
+try:
+ swap_info = sdk_services.in_progress_swap()
+except Exception as error:
+ # 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:
+
+
+Once you have a refundable swap in hand, use the following code to execute a refund:
+
+```python
+try:
+ refundables = sdk_services.list_refundables()
+except Exception as error:
+ # Handle error
+```
+
+Once you have a refundable swap in hand, use the follwing code to execute a refund:
+
+```python
+destination_address = "..."
+sat_per_vbyte =
+
+try:
+ sdk_services.refund(refundable.bitcoin_address, destination_address, sat_per_vbyte)
+except Exception as error:
+ # Handle error
+```
+
Go
diff --git a/src/guide/send_onchain.md b/src/guide/send_onchain.md
index c9a313d..bb8918d 100644
--- a/src/guide/send_onchain.md
+++ b/src/guide/send_onchain.md
@@ -155,6 +155,115 @@ try {
}
```
+Dart
+
+
+```dart
+try {
+ ReverseSwapPairInfo currentFees = await fetchReverseSwapFees();
+
+ 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}`);
+} catch (error) {
+ // 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:
+
+```dart
+print(`Minimum amount, in sats: ${currentFees.min}`);
+print(`Maximum amount, in sats: ${currentFees.max}`);
+```
+Once you checked the fees are acceptable, you can start the reverse swap:
+
+```dart
+String destinationAddress = "bc1..";
+int amountSat = currentFees.min;
+int satPerVbyte =
+try {
+ ReverseSwapInfo reverseSwapInfo = await sendOnchain(
+ amountSat: amountSat,
+ onchainRecipientAddress: destinationAddress,
+ pairHash: currentFees.feesHash,
+ satPerVbyte: satPerVbyte,
+ );
+} catch (error) {
+ // 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:
+
+```dart
+try {
+ List swaps = await inProgressReverseSwaps();
+ for (swap in swaps) {
+ print(`Reverse swap ${swap.id} in progress, status is ${swap.status}`);
+ }
+} catch (error) {
+ // handle error
+}
+```
+
+Python
+
+
+```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)
+except Exception as error:
+ # 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:
+
+```python
+print("Minimum amount, in sats: ", current_fees.min)
+print("Maximum amount, in sats: ", current_fees.max)
+```
+
+Once you checked the fees are acceptable, you can start the reverse swap:
+
+```python
+destination_address = "bc1.."
+amount_sat = current_fees.min
+
+try:
+ sdk.send_onchain(amount_sat, destination_address, current_fees.fees_hash)
+except Exception as error:
+ # Handle erorr
+```
+
+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:
+
+```python
+try:
+ reverse_swaps = sdk_services.in_progress_reverse_swaps()
+ for rs in reverse_swaps:
+ print("Reverse swap ",rs.id , " in progress, status is ", rs.status)
+except Exception as error:
+ # Handle erorr
+```
+
Go