mirror of
https://github.com/aljazceru/breez-sdk-docs.git
synced 2026-01-29 10:24:26 +01:00
Add Dart examples
This commit is contained in:
@@ -199,6 +199,74 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
The first step is to register a new node. In order to do that a seed is needed.
|
||||
## Registering a new node
|
||||
```dart
|
||||
try {
|
||||
Config config = await defaultConfig(configType: EnvironmentType.Production);
|
||||
Uint8List seed = await mnemonicToSeed(phrase: "<mnemonic words>");
|
||||
String inviteCode = "<your greenlight invite code>";
|
||||
|
||||
// registerNode takes either greenlight credentials (certifate & key) or invite code.
|
||||
// At this example we are using the invite code option.
|
||||
GreenlightCredentials credentials = await registerNode(network: Network.Bitcoin, seed: seed, config: config, inviteCode: inviteCode);
|
||||
} catch (error) {
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
|
||||
## Recovering an existing node
|
||||
```dart
|
||||
Config config = await defaultConfig(configType: EnvironmentType.Production);
|
||||
Uint8List seed = await mnemonicToSeed("<mnemonics words>");
|
||||
GreenlightCredentials credentials = await recoverNode(network: Network.Bitcoin, seed: seed, config: config);
|
||||
```
|
||||
|
||||
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
|
||||
```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
|
||||
Config config = await defaultConfig(configType: EnvironmentType.Production);
|
||||
|
||||
// Customize the config object according to your needs
|
||||
config.apiKey = "your API key";
|
||||
config.workingDir = "path to an existing directory";
|
||||
|
||||
try {
|
||||
await initServices(config: config, seed: seed, creds: creds);
|
||||
await startNode();
|
||||
} 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
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tabs>
|
||||
|
||||
You are now ready to receive a Lightning [payment](payments.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")
|
||||
@@ -42,4 +42,13 @@ 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.
|
||||
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: <relative-path-to>/breez-sdk/libs/sdk-flutter
|
||||
```
|
||||
@@ -73,6 +73,30 @@ try {
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
```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
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
</custom-tab>
|
||||
|
||||
|
||||
@@ -61,6 +61,30 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
```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
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tab>
|
||||
|
||||
## Supported Specs
|
||||
|
||||
@@ -61,6 +61,29 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
```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
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tab>
|
||||
|
||||
## Supported Specs
|
||||
|
||||
@@ -95,4 +95,46 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
## 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
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tabs>
|
||||
@@ -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,4 +143,59 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>x
|
||||
|
||||
```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<SwapInfo> 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 = <refund tx fee rate>
|
||||
try {
|
||||
String result = await refund(
|
||||
swapAddress: refundable.bitcoinAddress,
|
||||
toAddress: destinationAddress,
|
||||
satPerVbyte: satPerVbyte,
|
||||
);
|
||||
} catch (error) {
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tabs>
|
||||
@@ -121,8 +121,8 @@ of the total costs.
|
||||
Fetching the fees also tells you what is the range of amounts you can send:
|
||||
|
||||
```typescript
|
||||
console.log(`Minimum amount, in sats: ${current_fees.min}`);
|
||||
console.log(`Maximum amount, in sats: ${current_fees.max}`);
|
||||
console.log(`Minimum amount, in sats: ${currentFees.min}`);
|
||||
console.log(`Maximum amount, in sats: ${currentFees.max}`);
|
||||
```
|
||||
|
||||
Once you checked the fees are acceptable, you can start the reverse swap:
|
||||
@@ -155,6 +155,67 @@ try {
|
||||
}
|
||||
```
|
||||
</section>
|
||||
<div slot="title">Dart</div>
|
||||
<section>
|
||||
|
||||
```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 = <fee rate>
|
||||
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<ReverseSwapInfo> swaps = await inProgressReverseSwaps();
|
||||
for (swap in swaps) {
|
||||
print(`Reverse swap ${swap.id} in progress, status is ${swap.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
</section>
|
||||
</custom-tabs>
|
||||
If the reverse swap is successful, you'll get the on-chain payment on your destination address and the HODL invoice will
|
||||
change from pending to settled.
|
||||
|
||||
Reference in New Issue
Block a user