Getting started

The Breez SDK enables mobile developers to integrate Lightning and bitcoin payments into their apps with a very shallow learning curve. The use cases are endless – from social apps that want to integrate tipping between users to content-creation apps interested in adding bitcoin monetization. Crucially, this SDK is an end-to-end, non-custodial, drop-in solution powered by Greenlight, a built-in LSP, on-chain interoperability, third-party fiat on-ramps, and other services users and operators need.

The Breez SDK provides the following services:

  • Sending payments (via various protocols such as: bolt11, keysend, lnurl-pay, lightning address, btc address, etc.)
  • Receiving payments (via various protocols such as: bolt11, lnurl-withdraw, btc address, 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 node requires a seed (your master key). The seed is a bip39 mnemonic.

Pricing

The Breez SDK is free for developers.

API Key and Invite Code

Before you start, you will need an API Key to use the SDK, as well as an Invite Code when you create a new node.

To get both of them, please contact Breez via email at contact@breez.technology or at https://breez.technology/#contact-us-form

Support

Join this telegram group or email us at contact@breez.technology.

Installing

Breez SDK is available in several platforms. Follow the Installing page for instructions on how to install on your platform.

Connecting

The first step is to construct the SDK configuration. In it the environment and Greenlight node configuration is defined, whether you are using an invite code or partner credentials.

The SDK uses the config working directory to store the state of the SDK instance. Once a connection has been established with a node, the working directory can only be used for that node. When handling multiple instances of the SDK, one per node, each needs to have a different working directory defined.

Now you are ready to interact with the SDK.

Rust
let mnemonic = Mnemonic::generate_in(Language::English, 12)?;
let seed = mnemonic.to_seed("");
let invite_code = Some("<invite code>".into());
let api_key = "<api key>".into();

// Create the default config
let mut config = BreezServices::default_config(
    EnvironmentType::Production,
    api_key,
    breez_sdk_core::NodeConfig::Greenlight {
        config: GreenlightNodeConfig {
            partner_credentials: None,
            invite_code,
        },
    },
);

// Customize the config object according to your needs
config.working_dir = "path to an existing directory".into();

// Connect to the Breez SDK make it ready for use
let connect_request = ConnectRequest {
    config,
    seed: seed.to_vec(),
    restore_only: None,
};
let sdk = BreezServices::connect(connect_request, Box::new(AppEventListener {})).await?;
Swift
// SDK events listener
class SDKListener: EventListener {
    func onEvent(e: BreezEvent) {
        print("received event ", e)
    }
}

func gettingStarted() throws -> BlockingBreezServices? {
    // Create the default config
    let seed = try? mnemonicToSeed(phrase: "<mnemonic words>")

    let inviteCode = "<invite code>"
    let apiKey = "<api key>"
    var config = defaultConfig(envType: EnvironmentType.production, apiKey: apiKey,
                               nodeConfig: NodeConfig.greenlight(
                                   config: GreenlightNodeConfig(partnerCredentials: nil, inviteCode: inviteCode)))

    // Customize the config object according to your needs
    config.workingDir = "path to an existing directory"

    // Connect to the Breez SDK make it ready for use
    guard seed != nil else {
        return nil
    }
    let connectRequest = ConnectRequest(config: config, seed: seed!)
    let sdk = try? connect(req: connectRequest, listener: SDKListener())

    return sdk
}
Kotlin
// SDK events listener
class SDKListener : EventListener {
    override fun onEvent(e: BreezEvent) {
        // Log.v("SDKListener", "Received event $e")
    }
}

// Select your seed, invite code and eviroment
val seed = mnemonicToSeed("<mnemonic words>")
val inviteCode = "<invite code>"
val apiKey = "<api key>"

// Create the default config
val greenlightNodeConfig = GreenlightNodeConfig(null, inviteCode)
val nodeConfig = NodeConfig.Greenlight(greenlightNodeConfig)
val config = defaultConfig(EnvironmentType.PRODUCTION, apiKey, nodeConfig)

// Customize the config object according to your needs
config.workingDir = "path to an existing directory"

try {
    // Connect to the Breez SDK make it ready for use
    val connectRequest = ConnectRequest(config, seed)
    val sdk = connect(connectRequest, SDKListener())
} catch (e: Exception) {
    // handle error
}
React Native
// SDK events listener
const onBreezEvent = (e: BreezEvent) => {
  console.log(`Received event ${e.type}`)
}

try {
  // Create the default config
  const seed = await mnemonicToSeed('<mnemonics words>')
  const inviteCode = '<invite code>'
  const apiKey = '<api key>'
  const nodeConfig: NodeConfig = {
    type: NodeConfigVariant.GREENLIGHT,
    config: {
      inviteCode
    }
  }

  const config = await defaultConfig(
    EnvironmentType.PRODUCTION,
    apiKey,
    nodeConfig
  )

  // By default in React Native the workingDir is set it to:
  // `/<APPLICATION_SANDBOX_DIRECTORY>/breezSdk`
  // You can change this to another writable directory or a
  // subdirectory of the workingDir if managing multiple nodes.
  console.log(`Working directory: ${config.workingDir}`)
  // config.workingDir = "path to writable directory"

  // Connect to the Breez SDK make it ready for use
  const connectRequest: ConnectRequest = { config, seed }
  await connect(connectRequest, onBreezEvent)
} catch (err) {
  console.error(err)
}
Dart

// Initialize SDK logs listener
BreezSDK().initialize();

// Create the default config
Uint8List seed = await BreezSDK().mnemonicToSeed("<mnemonic words>");
String inviteCode = "<invite code>";
String apiKey = "<api key>";
NodeConfig nodeConfig = NodeConfig.greenlight(
  config: GreenlightNodeConfig(
    partnerCredentials: null,
    inviteCode: inviteCode,
  ),
);
Config config = await BreezSDK().defaultConfig(
  envType: EnvironmentType.Production,
  apiKey: apiKey,
  nodeConfig: nodeConfig,
);

// Customize the config object according to your needs
config = config.copyWith(workingDir: "path to an existing directory");

// Connect to the Breez SDK make it ready for use
ConnectRequest connectRequest = ConnectRequest(config: config, seed: seed);
return await BreezSDK().connect(req: connectRequest);
Python
class SDKListener(breez_sdk.EventListener):
    def on_event(self, event):
        logging.info(event)

def getting_started(API_KEY,mnemonic,temp_dir):
    
    seed = breez_sdk.mnemonic_to_seed(mnemonic)
    invite_code = "<invite code>"
    api_key = API_KEY
    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 = temp_dir

    try:
        # Connect to the Breez SDK make it ready for use
        connect_request = breez_sdk.ConnectRequest(config, seed)
        sdk_services = breez_sdk.connect(connect_request, SDKListener())
        
        return sdk_services
    except Exception as error:
        logging.error(error)
        raise
Go
// SDK events listener
type BreezListener struct{}

func (BreezListener) OnEvent(e breez_sdk.BreezEvent) {
    log.Printf("received event %#v", e)
}

func GettingStarted() *breez_sdk.BlockingBreezServices {
    // Create the default config
    seed, err := breez_sdk.MnemonicToSeed("<mnemonic words>")
    if err != nil {
        log.Fatalf("MnemonicToSeed failed: %#v", err)
    }

    inviteCode := "<invite code>"
    apiKey := "<api key>"
    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.WorkingDir = "path to an existing directory"

    connectRequest := breez_sdk.ConnectRequest{Config: config, Seed: seed}
    sdk, err := breez_sdk.Connect(connectRequest, BreezListener{})
    if err != nil {
        log.Fatalf("Connect failed: %#v", err)
    }

    return sdk
}

C#
public void GettingStarted()
{
    // Create the default config
    var seed = BreezSdkMethods.MnemonicToSeed("<mnemonic words>");
    var inviteCode = "<invite code>";
    var apiKey = "<api key>";
    var nodeConfig = new NodeConfig.Greenlight(
        new GreenlightNodeConfig(null, inviteCode)
    );
    var config = BreezSdkMethods.DefaultConfig(
        EnvironmentType.PRODUCTION,
        apiKey,
        nodeConfig
    ) with
    {
        // Customize the config object according to your needs
        workingDir = "path to an existing directory"
    };

    BlockingBreezServices sdk;
    try
    {
        // Connect to the Breez SDK make it ready for use
        var connectRequest = new ConnectRequest(config, seed);
        sdk = BreezSdkMethods.Connect(connectRequest, new SdkListener());
    }
    catch (Exception)
    {
        // Handle error
    }
}

// SDK event listener
class SdkListener : EventListener
{
    public void OnEvent(BreezEvent e)
    {
        Console.WriteLine($"Received Breez event type {e.GetType().Name}");
    }
}

Developer note

By default the config working directory is set to ./. Some platforms may require that you use an application specific directory that is writable within the application sandbox. For example applications running on Android or iOS.


To connect to an already existing node without registering a new one, use the restore_only flag in the connect request. If the node does not exist it will result in an error.

Rust
let connect_request = ConnectRequest {
    config,
    seed,
    restore_only: Some(true),
};
let sdk = BreezServices::connect(connect_request, Box::new(AppEventListener {})).await?;
Swift
let connectRequest = ConnectRequest(config: config, seed: seed, restoreOnly: true)
let sdk = try? connect(req: connectRequest, listener: SDKListener())
Kotlin
val connectRequest = ConnectRequest(config, seed, true)
val sdk = connect(connectRequest, SDKListener())
React Native
const connectRequest: ConnectRequest = { config, seed, restoreOnly: true }
await connect(connectRequest, onBreezEvent)
Dart
ConnectRequest connectRequest = ConnectRequest(config: config, seed: seed, restoreOnly: true);
return await BreezSDK().connect(req: connectRequest);
Python
connect_request = breez_sdk.ConnectRequest(config, seed, restore_only=True)
sdk_services = breez_sdk.connect(connect_request, SDKListener())
Go
restoreOnly := true
connectRequest := breez_sdk.ConnectRequest{
    Config:      config,
    Seed:        seed,
    RestoreOnly: &restoreOnly,
}
sdk, err := breez_sdk.Connect(connectRequest, BreezListener{})
C#
var connectRequest = new ConnectRequest(config, seed, true);
sdk = BreezSdkMethods.Connect(connectRequest, new SdkListener());

Getting the Node State

At any point we can fetch our balance from the Greenlight node:

Rust
let node_state = sdk.node_info()?;
let balance_ln = node_state.channels_balance_msat;
let balance_onchain = node_state.onchain_balance_msat;
Swift
if let nodeInfo = try? sdk.nodeInfo() {
    let lnBalance = nodeInfo.channelsBalanceMsat
    let onchainBalance = nodeInfo.onchainBalanceMsat
    print(lnBalance);
    print(onchainBalance);
}
Kotlin
try {
    val nodeInfo = sdk.nodeInfo()
    val lnBalance = nodeInfo?.channelsBalanceMsat
    val onchainBalance = nodeInfo?.onchainBalanceMsat
} catch (e: Exception) {
    // handle error
}
React Native
try {
  const nodeState = await nodeInfo()
  const balanceLn = nodeState.channelsBalanceMsat
  const balanceOnchain = nodeState.onchainBalanceMsat
} catch (err) {
  console.error(err)
}
Dart
NodeState? nodeInfo = await BreezSDK().nodeInfo();
if (nodeInfo != null) {
  int lnBalance = nodeInfo.channelsBalanceMsat;
  int onchainBalance = nodeInfo.onchainBalanceMsat;
  print(lnBalance);
  print(onchainBalance);
}
Python
node_info = sdk_services.node_info()
ln_balance = node_info.channels_balance_msat
onchain_balance = node_info.onchain_balance_msat
Go
if nodeInfo, err := sdk.NodeInfo(); err == nil {
    lnBalance := nodeInfo.ChannelsBalanceMsat
    onchainBalance := nodeInfo.OnchainBalanceMsat

    log.Printf("%#v %#v", lnBalance, onchainBalance)
}
C#
try
{
    var nodeInfo = sdk.NodeInfo();
    var lnBalance = nodeInfo?.channelsBalanceMsat;
    var onchainBalance = nodeInfo?.onchainBalanceMsat;
}
catch (Exception)
{
    // Handle error
}

You are now ready to receive a Lightning payment.