mirror of
https://github.com/aljazceru/breez-sdk-docs.git
synced 2025-12-17 13:54:20 +01:00
Merge branch 'connect-api' into go-examples
# Conflicts: # src/guide/getting_started.md # src/guide/lnurl_auth.md # src/guide/lnurl_pay.md # src/guide/lnurl_withdraw.md # src/guide/payments.md # src/guide/receive_onchain.md # src/guide/send_onchain.md
This commit is contained in:
10
README.md
10
README.md
@@ -6,3 +6,13 @@ The SDK docs are live at [https://sdk-doc.breez.technology](https://sdk-doc.bree
|
|||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
For syntax and supported features, see [https://rust-lang.github.io/mdBook](https://rust-lang.github.io/mdBook).
|
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
|
||||||
|
```
|
||||||
|
|||||||
@@ -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.)
|
* 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 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
|
## Installing
|
||||||
|
|
||||||
@@ -19,44 +19,30 @@ Breez SDK is available in several platforms. Follow the [Installing](install.md)
|
|||||||
<div slot="title">Rust</div>
|
<div slot="title">Rust</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
The first step is to register a new node. In order to do that a seed is needed.
|
## Connecting
|
||||||
## Registering a new node
|
|
||||||
```rust,no_run
|
|
||||||
let seed = <your seed>;
|
|
||||||
let invite_code = <your greenlight 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 = <your 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
|
|
||||||
```rust,no_run
|
```rust,no_run
|
||||||
// Create the default config
|
// 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
|
// 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();
|
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,
|
config,
|
||||||
seed.to_vec(),
|
seed.to_vec(),
|
||||||
credentials.clone(),
|
|
||||||
Box::new(AppEventListener {}),
|
Box::new(AppEventListener {}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
BreezServices::start(rt(), &sdk).await?;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
At any point we can fetch our balance from the Greenlight node:
|
At any point we can fetch our balance from the Greenlight node:
|
||||||
@@ -71,35 +57,7 @@ if let Some(node_state) = sdk.node_info()? {
|
|||||||
<div slot="title">Swift</div>
|
<div slot="title">Swift</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
The first step is to register a new node
|
## Connecting
|
||||||
## Registering a new node
|
|
||||||
```swift
|
|
||||||
do {
|
|
||||||
let seed = try mnemonicToSeed(phrase: "<mnemonics words>")
|
|
||||||
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: "<mnemonics words>")
|
|
||||||
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
|
|
||||||
```swift
|
```swift
|
||||||
|
|
||||||
// SDK events listener
|
// SDK events listener
|
||||||
@@ -110,15 +68,18 @@ class SDKListener: EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the default config
|
// Create the default config
|
||||||
var config = defaultConfig(envType: EnvironmentType.production)
|
let seed = try mnemonicToSeed(phrase: "<mnemonics words>")
|
||||||
|
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
|
// 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 {
|
do {
|
||||||
let sdk = try initServices(config: config, seed: seed, creds: credentials, listener: SDKListener());
|
// Connect to the Breez SDK make it ready for use
|
||||||
try sdk.start();
|
let sdk = try connect(config: config, seed: seed, listener: SDKListener());
|
||||||
} catch{
|
} catch{
|
||||||
// handle error
|
// handle error
|
||||||
}
|
}
|
||||||
@@ -140,31 +101,7 @@ do {
|
|||||||
<div slot="title">React Native</div>
|
<div slot="title">React Native</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
The first step is to register a new node
|
## Connecting
|
||||||
## Registering a new node
|
|
||||||
```typescript
|
|
||||||
try {
|
|
||||||
const seed = await mnemonicToSeed("<mnemonics words>");
|
|
||||||
const inviteCode = "<your greenlight invite code>";
|
|
||||||
|
|
||||||
// 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("<mnemonics words>");
|
|
||||||
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
|
|
||||||
```typescript
|
```typescript
|
||||||
|
|
||||||
// SDK events listener
|
// SDK events listener
|
||||||
@@ -173,15 +110,22 @@ addEventListener((type, data) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Create the default config
|
// Create the default config
|
||||||
let config = defaultConfig(EnvironmentType.PRODUCTION)
|
const seed = await mnemonicToSeed("<mnemonics words>");
|
||||||
|
const inviteCode = "<your greenlight invite code>";
|
||||||
|
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
|
// 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";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sdkServices = await initServices(config, credentials.deviceKey, credentials.deviceCert, seed);
|
// Connect to the Breez SDK make it ready for use
|
||||||
await start();
|
const sdkServices = await connect(config, seed);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@@ -199,32 +143,90 @@ try {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</section>
|
||||||
|
<div slot="title">Dart</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
## 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: "<mnemonic words>");
|
||||||
|
String inviteCode = "<your greenlight invite code>";
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</section>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
## 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("<mnemonics words>")
|
||||||
|
invite_code = "<your greenlight 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
|
||||||
|
```
|
||||||
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
The first step is to register a new node
|
## Connecting
|
||||||
## Registering a new node
|
|
||||||
```go
|
|
||||||
if seed, err := breez_sdk.MnemonicToSeed("<mnemonics words>"); err != nil {
|
|
||||||
inviteCode := "<your greenlight invite code>"
|
|
||||||
|
|
||||||
// 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("<mnemonics words>"); 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
|
|
||||||
```go
|
```go
|
||||||
// SDK events listener
|
// SDK events listener
|
||||||
type BreezListener struct{}
|
type BreezListener struct{}
|
||||||
@@ -234,17 +236,24 @@ func (BreezListener) OnEvent(e breez_sdk.BreezEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the default config
|
// Create the default config
|
||||||
config := breez_sdk.DefaultConfig(breez_sdk.EnvironmentTypeProduction)
|
apiKey := "<your breez api key>"
|
||||||
|
inviteCode := "<your greenlight invite code>"
|
||||||
|
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
|
// 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"
|
||||||
|
|
||||||
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()
|
sdkServices.Start()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
At any point we can fetch our balance from the Greenlight node:
|
At any point we can fetch our balance from the Greenlight node:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
|||||||
@@ -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:
|
To do so, add the following to your Gradle dependencies:
|
||||||
|
|
||||||
``` groovy
|
```gradle
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url("https://mvn.breez.technology/releases")
|
url("https://mvn.breez.technology/releases")
|
||||||
@@ -51,3 +51,15 @@ Currently c# is built from source only. Please visit the [sdk-bindings](https://
|
|||||||
## rust
|
## 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
|
||||||
|
```
|
||||||
|
## 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.
|
||||||
|
|||||||
@@ -73,6 +73,51 @@ 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>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
@@ -93,11 +138,9 @@ if input, err := breez_sdk.ParseInput(lnurlAuthUrl); err != nil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</custom-tab>
|
</custom-tabs>
|
||||||
|
|
||||||
## Supported Specs
|
## Supported Specs
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,48 @@ try {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</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>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
@@ -83,7 +125,6 @@ if input, err := breez_sdk.ParseInput(lnurlPayUrl); err != nil {
|
|||||||
</custom-tab>
|
</custom-tab>
|
||||||
|
|
||||||
## Supported Specs
|
## Supported Specs
|
||||||
|
|
||||||
- [LUD-01](https://github.com/lnurl/luds/blob/luds/01.md) LNURL bech32 encoding
|
- [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-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
|
- [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) LN Address
|
||||||
|
|||||||
@@ -61,6 +61,46 @@ try {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</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>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,81 @@ try {
|
|||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
</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>
|
||||||
|
<div slot="title">Python</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:
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
@@ -117,5 +192,6 @@ payment, err := sdkServices.SendPayment(bolt11, 3000)
|
|||||||
const nodeId = "...";
|
const nodeId = "...";
|
||||||
payment, err := sdkServices.SendSpontaneousPayment(nodeId, 3000)
|
payment, err := sdkServices.SendSpontaneousPayment(nodeId, 3000)
|
||||||
```
|
```
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</custom-tabs>
|
</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?
|
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
|
```rust,no_run
|
||||||
let destination_address = "...".into()
|
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
|
```swift
|
||||||
let destinationAddress = "..."
|
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
|
```typescript
|
||||||
const destinationAddress = "..."
|
const destinationAddress = "..."
|
||||||
@@ -143,6 +143,109 @@ try {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</section>
|
||||||
|
<div slot="title">Dart</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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 = <refund tx fee rate>
|
||||||
|
|
||||||
|
try:
|
||||||
|
sdk_services.refund(refundable.bitcoin_address, destination_address, sat_per_vbyte)
|
||||||
|
except Exception as error:
|
||||||
|
# Handle error
|
||||||
|
```
|
||||||
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,115 @@ try {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
</section>
|
</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>
|
||||||
|
<div slot="title">Python</div>
|
||||||
|
<section>
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
</section>
|
||||||
<div slot="title">Go</div>
|
<div slot="title">Go</div>
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user