Customizing the SDK
Using the SDK Builder gives you more control over the initialization and modular components used when the SDK is running. Below you can find examples of initializing the SDK using the SDK Builder and implementing modular components:
- Storage to manage stored data
- PostgreSQL Storage as an alternative storage backend
- Bitcoin Chain Service to provide network data
- LNURL Client to make REST requests
- Fiat Service to provide Fiat currencies and exchange rates
- Change the Key Set to alter the derivation path used
- Payment Observer to be notified before payments occur
// Construct the seed using mnemonic words or entropy bytes
let mnemonic = "<mnemonic words>".to_string();
let seed = Seed::Mnemonic {
mnemonic,
passphrase: None,
};
// Create the default config
let mut config = default_config(Network::Mainnet);
config.api_key = Some("<breez api key>".to_string());
// Build the SDK using the config, seed and default storage
let builder = SdkBuilder::new(config, seed).with_default_storage("./.data".to_string());
// You can also pass your custom implementations:
// let builder = builder.with_storage(<your storage implementation>)
// let builder = builder.with_chain_service(<your chain service implementation>)
// let builder = builder.with_rest_client(<your rest client implementation>)
// let builder = builder.with_key_set(KeySetConfig { key_set_type: <your key set type>, use_address_index: <use address index>, account_number: <account number> })
// let builder = builder.with_payment_observer(<your payment observer implementation>);
let sdk = builder.build().await?;
// Construct the seed using mnemonic words or entropy bytes
let mnemonic = "<mnemonic words>"
let seed = Seed.mnemonic(mnemonic: mnemonic, passphrase: nil)
// Create the default config
var config = defaultConfig(network: Network.mainnet)
config.apiKey = "<breez api key>"
// Build the SDK using the config, seed and default storage
let builder = SdkBuilder(config: config, seed: seed)
await builder.withDefaultStorage(storageDir: "./.data")
// You can also pass your custom implementations:
// await builder.withStorage(<your storage implementation>)
// await builder.withChainService(<your chain service implementation>)
// await builder.withRestClient(<your rest client implementation>)
// await builder.withKeySet(<your key set type>, <use address index>, <account number>)
// await builder.withPaymentObserver(<your payment observer implementation>)
let sdk = try await builder.build()
// Construct the seed using mnemonic words or entropy bytes
val mnemonic = "<mnemonic words>"
val seed = Seed.Mnemonic(mnemonic, null)
// Create the default config
val config = defaultConfig(Network.MAINNET)
config.apiKey = "<breez api key>"
try {
// Build the SDK using the config, seed and default storage
val builder = SdkBuilder(config, seed)
builder.withDefaultStorage("./.data")
// You can also pass your custom implementations:
// builder.withStorage(<your storage implementation>)
// builder.withChainService(<your chain service implementation>)
// builder.withRestClient(<your rest client implementation>)
// builder.withKeySet(<your key set type>, <use address index>, <account number>)
// builder.withPaymentObserver(<your payment observer implementation>)
val sdk = builder.build()
} catch (e: Exception) {
// handle error
}
// Construct the seed using mnemonic words or entropy bytes
var mnemonic = "<mnemonic words>";
var seed = new Seed.Mnemonic(mnemonic: mnemonic, passphrase: null);
// Create the default config
var config = BreezSdkSparkMethods.DefaultConfig(Network.Mainnet) with
{
apiKey = "<breez api key>"
};
// Build the SDK using the config, seed and default storage
var builder = new SdkBuilder(config: config, seed: seed);
await builder.WithDefaultStorage(storageDir: "./.data");
// You can also pass your custom implementations:
// await builder.WithStorage(<your storage implementation>)
// await builder.WithChainService(<your chain service implementation>)
// await builder.WithRestClient(<your rest client implementation>)
// await builder.WithKeySet(<your key set type>, <use address index>, <account number>)
// await builder.WithPaymentObserver(<your payment observer implementation>);
var sdk = await builder.Build();
// Call init when using the SDK in a web environment before calling any other SDK
// methods. This is not needed when using the SDK in a Node.js/Deno environment.
await init()
// Construct the seed using mnemonic words or entropy bytes
const mnemonic = '<mnemonic words>'
const seed: Seed = { type: 'mnemonic', mnemonic, passphrase: undefined }
// Create the default config
const config = defaultConfig('mainnet')
config.apiKey = '<breez api key>'
// Build the SDK using the config, seed and default storage
let builder = SdkBuilder.new(config, seed)
builder = await builder.withDefaultStorage('./.data')
// You can also pass your custom implementations:
// builder = builder.withStorage(<your storage implementation>)
// builder = builder.withChainService(<your chain service implementation>)
// builder = builder.withRestClient(<your rest client implementation>)
// builder = builder.withKeySet({ keySetType: <your key set type>, useAddressIndex: <use address index>, accountNumber: <account number> })
// builder = builder.withPaymentObserver(<your payment observer implementation>)
const sdk = await builder.build()
// Construct the seed using mnemonic words or entropy bytes
const mnemonic = '<mnemonics words>'
const seed = new Seed.Mnemonic({ mnemonic, passphrase: undefined })
// Create the default config
const config = defaultConfig(Network.Mainnet)
config.apiKey = '<breez api key>'
// Build the SDK using the config, seed and default storage
const builder = new SdkBuilder(config, seed)
await builder.withDefaultStorage(`${RNFS.DocumentDirectoryPath}/data`)
// You can also pass your custom implementations:
// await builder.withStorage(<your storage implementation>)
// await builder.withChainService(<your chain service implementation>)
// await builder.withRestClient(<your rest client implementation>)
// await builder.withKeySet({ keySetType: <your key set type>, useAddressIndex: <use address index>, accountNumber: <account number> })
// await builder.withPaymentObserver(<your payment observer implementation>)
const sdk = await builder.build()
// Construct the seed using mnemonic words or entropy bytes
String mnemonic = "<mnemonic words>";
final seed = Seed.mnemonic(mnemonic: mnemonic, passphrase: null);
// Create the default config
final config = defaultConfig(network: Network.mainnet)
.copyWith(apiKey: "<breez api key>");
// Build the SDK using the config, seed and default storage
final builder = SdkBuilder(config: config, seed: seed);
builder.withDefaultStorage(storageDir: "./.data");
// You can also pass your custom implementations:
// builder.withRestChainService(
// url: "https://custom.chain.service",
// credentials: Credentials(
// username: "service-username", password: "service-password"));
// builder.withKeySet(config: KeySetConfig(keySetType: <your key set type>, useAddressIndex: <use address index>, accountNumber: <account number>));
final sdk = await builder.build();
# Construct the seed using mnemonic words or entropy bytes
mnemonic = "<mnemonic words>"
seed = Seed.MNEMONIC(mnemonic=mnemonic, passphrase=None)
# Create the default config
config = default_config(network=Network.MAINNET)
config.api_key = "<breez api key>"
try:
# Build the SDK using the config, seed and default storage
builder = SdkBuilder(config=config, seed=seed)
await builder.with_default_storage(storage_dir="./.data")
# You can also pass your custom implementations:
# await builder.with_storage(<your storage implementation>)
# await builder.with_chain_service(<your chain service implementation>)
# await builder.with_rest_client(<your rest client implementation>)
# await builder.with_key_set(<your key set type>, <use address index>, <account number>)
# await builder.with_payment_observer(<your payment observer implementation>)
sdk = await builder.build()
return sdk
except Exception as error:
logging.error(error)
raise
// Construct the seed using mnemonic words or entropy bytes
mnemonic := "<mnemonic words>"
var seed breez_sdk_spark.Seed = breez_sdk_spark.SeedMnemonic{
Mnemonic: mnemonic,
Passphrase: nil,
}
// Create the default config
apiKey := "<breez api key>"
config := breez_sdk_spark.DefaultConfig(breez_sdk_spark.NetworkMainnet)
config.ApiKey = &apiKey
// Build the SDK using the config, seed and default storage
builder := breez_sdk_spark.NewSdkBuilder(config, seed)
builder.WithDefaultStorage("./.data")
// You can also pass your custom implementations:
// builder.WithStorage(<your storage implementation>)
// builder.WithChainService(<your chain service implementation>)
// builder.WithRestClient(<your rest client implementation>)
// builder.WithKeySet(<your key set type>, <use address index>, <account number>)
// builder.WithPaymentObserver(<your payment observer implementation>)
sdk, err := builder.Build()
return sdk, err
With Storage API docs
When using the SDK Builder, you either have to provide a Storage implementation or use the default storage from the SDK.
Note: Flutter currently only supports using the default storage.
With PostgreSQL Storage API docs
The SDK includes a PostgreSQL storage implementation as an alternative. This is useful for environments where file-based storage may not be suitable.
Note: Not available for Javascript, React Native or Flutter.
// Construct the seed using mnemonic words or entropy bytes
let mnemonic = "<mnemonic words>".to_string();
let seed = Seed::Mnemonic {
mnemonic,
passphrase: None,
};
// Create the default config
let mut config = default_config(Network::Mainnet);
config.api_key = Some("<breez api key>".to_string());
// Configure PostgreSQL storage
// Connection string format: "host=localhost user=postgres password=secret dbname=spark"
// Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
let mut postgres_config =
default_postgres_storage_config("host=localhost user=postgres dbname=spark".to_string());
// Optionally pool settings can be adjusted. Some examples:
postgres_config.max_pool_size = 8; // Max connections in pool
postgres_config.wait_timeout_secs = Some(30); // Timeout waiting for connection
// Create the storage and build the SDK
let storage = create_postgres_storage(postgres_config).await?;
let sdk = SdkBuilder::new(config, seed)
.with_storage(storage)
.build()
.await?;
// Construct the seed using mnemonic words or entropy bytes
let mnemonic = "<mnemonic words>"
let seed = Seed.mnemonic(mnemonic: mnemonic, passphrase: nil)
// Create the default config
var config = defaultConfig(network: Network.mainnet)
config.apiKey = "<breez api key>"
// Configure PostgreSQL storage
// Connection string format: "host=localhost user=postgres password=secret dbname=spark"
// Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
var postgresConfig = defaultPostgresStorageConfig(
connectionString: "host=localhost user=postgres dbname=spark"
)
// Optionally pool settings can be adjusted. Some examples:
postgresConfig.maxPoolSize = UInt32(8) // Max connections in pool
postgresConfig.waitTimeoutSecs = UInt64(30) // Timeout waiting for connection
// Create the storage and build the SDK
let storage = try await createPostgresStorage(config: postgresConfig)
let builder = SdkBuilder(config: config, seed: seed)
await builder.withStorage(storage: storage)
let sdk = try await builder.build()
// Construct the seed using mnemonic words or entropy bytes
val mnemonic = "<mnemonic words>"
val seed = Seed.Mnemonic(mnemonic, null)
// Create the default config
val config = defaultConfig(Network.MAINNET)
config.apiKey = "<breez api key>"
// Configure PostgreSQL storage
// Connection string format: "host=localhost user=postgres password=secret dbname=spark"
// Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
val postgresConfig = defaultPostgresStorageConfig("host=localhost user=postgres dbname=spark")
// Optionally pool settings can be adjusted. Some examples:
postgresConfig.maxPoolSize = 8u // Max connections in pool
postgresConfig.waitTimeoutSecs = 30u // Timeout waiting for connection
try {
// Create the storage and build the SDK
val storage = createPostgresStorage(postgresConfig)
val builder = SdkBuilder(config, seed)
builder.withStorage(storage)
val sdk = builder.build()
} catch (e: Exception) {
// handle error
}
// Construct the seed using mnemonic words or entropy bytes
var mnemonic = "<mnemonic words>";
var seed = new Seed.Mnemonic(mnemonic: mnemonic, passphrase: null);
// Create the default config
var config = BreezSdkSparkMethods.DefaultConfig(Network.Mainnet) with
{
apiKey = "<breez api key>"
};
// Configure PostgreSQL storage
// Connection string format: "host=localhost user=postgres password=secret dbname=spark"
// Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
var postgresConfig = BreezSdkSparkMethods.DefaultPostgresStorageConfig(
connectionString: "host=localhost user=postgres dbname=spark"
);
// Optionally pool settings can be adjusted. Some examples:
postgresConfig = postgresConfig with
{
maxPoolSize = 8u, // Max connections in pool
waitTimeoutSecs = 30ul // Timeout waiting for connection
};
// Create the storage and build the SDK
var storage = await BreezSdkSparkMethods.CreatePostgresStorage(config: postgresConfig);
var builder = new SdkBuilder(config: config, seed: seed);
await builder.WithStorage(storage);
var sdk = await builder.Build();
async def init_sdk_postgres():
# Construct the seed using mnemonic words or entropy bytes
mnemonic = "<mnemonic words>"
seed = Seed.MNEMONIC(mnemonic=mnemonic, passphrase=None)
# Create the default config
config = default_config(network=Network.MAINNET)
config.api_key = "<breez api key>"
# Configure PostgreSQL storage
# Connection string format: "host=localhost user=postgres password=secret dbname=spark"
# Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
postgres_config = default_postgres_storage_config(
connection_string="host=localhost user=postgres dbname=spark"
)
# Optionally pool settings can be adjusted. Some examples:
postgres_config.max_pool_size = 8 # Max connections in pool
postgres_config.wait_timeout_secs = 30 # Timeout waiting for connection
try:
# Create the storage and build the SDK
storage = await create_postgres_storage(config=postgres_config)
builder = SdkBuilder(config=config, seed=seed)
await builder.with_storage(storage=storage)
sdk = await builder.build()
return sdk
except Exception as error:
logging.error(error)
raise
// Construct the seed using mnemonic words or entropy bytes
mnemonic := "<mnemonic words>"
var seed breez_sdk_spark.Seed = breez_sdk_spark.SeedMnemonic{
Mnemonic: mnemonic,
Passphrase: nil,
}
// Create the default config
apiKey := "<breez api key>"
config := breez_sdk_spark.DefaultConfig(breez_sdk_spark.NetworkMainnet)
config.ApiKey = &apiKey
// Configure PostgreSQL storage
// Connection string format: "host=localhost user=postgres password=secret dbname=spark"
// Or URI format: "postgres://user:password@host:port/dbname?sslmode=require"
postgresConfig := breez_sdk_spark.DefaultPostgresStorageConfig("host=localhost user=postgres dbname=spark")
// Optionally pool settings can be adjusted. Some examples:
postgresConfig.MaxPoolSize = 8 // Max connections in pool
waitTimeoutSecs := uint64(30)
postgresConfig.WaitTimeoutSecs = &waitTimeoutSecs // Timeout waiting for connection
// Create the storage and build the SDK
storage, err := breez_sdk_spark.CreatePostgresStorage(postgresConfig)
if err != nil {
return nil, err
}
builder := breez_sdk_spark.NewSdkBuilder(config, seed)
builder.WithStorage(storage)
sdk, err := builder.Build()
if err != nil {
return nil, err
}
Developer note
Sharing the same PostgreSQL database with multiple SDK instances is incompatible with real-time sync. See Real-time sync server URL for how to disable it.
With Chain Service API docs
The SDK provides a default Bitcoin Chain Service implementation. If you want to use your own, you can provide it either by using With REST Chain Service or by implementing the Bitcoin Chain Service interface.
With REST Chain Service API docs
The SDK provides a default Bitcoin Chain Service implementation. If you want to use your own, you can provide it either by using With Chain Service or by providing a URL and optional credentials.
let url = "<your REST chain service URL>".to_string();
let chain_api_type = ChainApiType::MempoolSpace;
let optional_credentials = Credentials {
username: "<username>".to_string(),
password: "<password>".to_string(),
};
builder.with_rest_chain_service(url, chain_api_type, Some(optional_credentials))
let url = "<your REST chain service URL>"
let chainApiType = ChainApiType.mempoolSpace
let optionalCredentials = Credentials(
username: "<username>",
password: "<password>"
)
await builder.withRestChainService(
url: url,
apiType: chainApiType,
credentials: optionalCredentials
)
val url = "<your REST chain service URL>"
val chainApiType = ChainApiType.MEMPOOL_SPACE
val optionalCredentials = Credentials(
username = "<username>",
password = "<password>"
)
builder.withRestChainService(
url = url,
apiType = chainApiType,
credentials = optionalCredentials
)
var url = "<your REST chain service URL>";
var chainApiType = ChainApiType.MempoolSpace;
var optionalCredentials = new Credentials(
username: "<username>",
password: "<password>"
);
await builder.WithRestChainService(
url: url,
apiType: chainApiType,
credentials: optionalCredentials
);
const url = '<your REST chain service URL>'
const chainApiType = 'mempoolSpace'
const optionalCredentials: Credentials = {
username: '<username>',
password: '<password>'
}
builder = builder.withRestChainService(url, chainApiType, optionalCredentials)
const url = '<your REST chain service URL>'
const chainApiType = ChainApiType.MempoolSpace
const optionalCredentials: Credentials = {
username: '<username>',
password: '<password>'
}
await builder.withRestChainService(url, chainApiType, optionalCredentials)
String url = "<your REST chain service URL>";
var chainApiType = ChainApiType.mempoolSpace;
var optionalCredentials = Credentials(
username: "<username>",
password: "<password>",
);
builder.withRestChainService(
url: url,
apiType: chainApiType,
credentials: optionalCredentials,
);
url = "<your REST chain service URL>"
chain_api_type = ChainApiType.MEMPOOL_SPACE
optional_credentials = Credentials(
username="<username>",
password="<password>",
)
await builder.with_rest_chain_service(
url=url,
api_type=chain_api_type,
credentials=optional_credentials,
)
url := "<your REST chain service URL>"
chainApiType := breez_sdk_spark.ChainApiTypeMempoolSpace
optionalCredentials := &breez_sdk_spark.Credentials{
Username: "<username>",
Password: "<password>",
}
builder.WithRestChainService(url, chainApiType, optionalCredentials)
With Fiat Service API docs
The SDK by default provides a list of available Fiat currencies and current exchange rates. If you want to use your own, you can provide it by implementing the Fiat Service interface.
With LNURL Client API docs
The LNURL Client is used to make REST requests specifically when interacting with LNURL. If you want to use your own, you can it provide by implementing the REST Service interface.
With Key Set API docs
The SDK uses by default the Default key set with the account number 1 on Mainnet (0 on Regtest). You can change this to alter the derivation path used with the provided seed:
- Default - Uses derivation path
m/8797555'/<account number>(use address index is ignored) - Taproot - Uses derivation path
m/86'/0'/<account number>'/0/0
(orm/86'/0'/0'/0/<account number>when use address index is enabled) - Native Segwit - Uses derivation path
m/84'/0'/<account number>'/0/0
(orm/84'/0'/0'/0/<account number>when use address index is enabled) - Wrapped Segwit - Uses derivation path
m/49'/0'/<account number>'/0/0
(orm/49'/0'/0'/0/<account number>when use address index is enabled) - Legacy - Uses derivation path
m/44'/0'/<account number>'/0/0
(orm/44'/0'/0'/0/<account number>when use address index is enabled)
let key_set_type = KeySetType::Default;
let use_address_index = false;
let optional_account_number = 21;
builder.with_key_set(KeySetConfig {
key_set_type,
use_address_index,
account_number: Some(optional_account_number),
})
let keySetType = KeySetType.default
let useAddressIndex = false
let optionalAccountNumber = UInt32(21)
let config = KeySetConfig(
keySetType: keySetType,
useAddressIndex: useAddressIndex,
accountNumber: optionalAccountNumber
)
await builder.withKeySet(config: config)
val keySetType = KeySetType.DEFAULT
val useAddressIndex = false
val optionalAccountNumber = 21u
val keySetConfig = KeySetConfig(
keySetType = keySetType,
useAddressIndex = useAddressIndex,
accountNumber = optionalAccountNumber
)
builder.withKeySet(keySetConfig)
var keySetType = KeySetType.Default;
var useAddressIndex = false;
var optionalAccountNumber = 21u;
var keySetConfig = new KeySetConfig(
keySetType: keySetType,
useAddressIndex: useAddressIndex,
accountNumber: optionalAccountNumber
);
await builder.WithKeySet(keySetConfig);
builder = builder.withKeySet({
keySetType: 'default',
useAddressIndex: false,
accountNumber: 21
})
const keySetConfig: KeySetConfig = {
keySetType: KeySetType.Default,
useAddressIndex: false,
accountNumber: 21
}
await builder.withKeySet(keySetConfig)
var keySetType = KeySetType.default_;
var useAddressIndex = false;
var optionalAccountNumber = 21;
builder.withKeySet(
config: KeySetConfig(
keySetType: keySetType,
useAddressIndex: useAddressIndex,
accountNumber: optionalAccountNumber,
),
);
key_set_type = KeySetType.DEFAULT
use_address_index = False
optional_account_number = 21
key_set_config = KeySetConfig(
key_set_type=key_set_type,
use_address_index=use_address_index,
account_number=optional_account_number,
)
await builder.with_key_set(config=key_set_config)
keySetType := breez_sdk_spark.KeySetTypeDefault
useAccountIndex := true
optionalAccountNumber := uint32(21)
keySetConfig := breez_sdk_spark.KeySetConfig{
KeySetType: keySetType,
UseAddressIndex: useAccountIndex,
AccountNumber: &optionalAccountNumber,
}
builder.WithKeySet(keySetConfig)
With Payment Observer API docs
By implementing the Payment Observer interface you can be notified before a payment is sent. It includes information about the provisional payment including the payment ID, amount to be sent (in satoshis or token base units) and payment details based on the payment method.
Note: Flutter currently does not support this.
pub(crate) struct ExamplePaymentObserver {}
#[async_trait]
impl PaymentObserver for ExamplePaymentObserver {
async fn before_send(
&self,
payments: Vec<ProvisionalPayment>,
) -> Result<(), PaymentObserverError> {
for payment in payments {
info!(
"About to send payment: {:?} of amount {:?}",
payment.payment_id, payment.amount
);
}
Ok(())
}
}
pub(crate) fn with_payment_observer(builder: SdkBuilder) -> SdkBuilder {
let observer = ExamplePaymentObserver {};
builder.with_payment_observer(Arc::new(observer))
}
class ExamplePaymentObserver: PaymentObserver {
func beforeSend(payments: [ProvisionalPayment]) async {
for payment in payments {
print("About to send payment: \(payment.paymentId) of amount \(payment.amount)")
}
}
}
func withPaymentObserver(builder: SdkBuilder) async {
let paymentObserver = ExamplePaymentObserver()
await builder.withPaymentObserver(paymentObserver: paymentObserver)
}
class ExamplePaymentObserver : PaymentObserver {
override suspend fun beforeSend(payments: List<ProvisionalPayment>) {
for (payment in payments) {
// Log.v("PaymentObserver", "About to send payment: ${payment.paymentId} of amount ${payment.amount}")
}
}
}
suspend fun withPaymentObserver(builder: SdkBuilder) {
val paymentObserver = ExamplePaymentObserver()
builder.withPaymentObserver(paymentObserver)
}
class ExamplePaymentObserver : PaymentObserver
{
public async Task BeforeSend(List<ProvisionalPayment> payments)
{
foreach (var payment in payments)
{
Console.WriteLine($"About to send payment {payment.paymentId} of amount {payment.amount}");
}
}
}
async Task WithPaymentObserver(SdkBuilder builder)
{
var paymentObserver = new ExamplePaymentObserver();
await builder.WithPaymentObserver(paymentObserver);
}
class ExamplePaymentObserver {
beforeSend = async (payments: ProvisionalPayment[]) => {
for (const payment of payments) {
console.log(`About to send payment: ${payment.paymentId} of amount ${payment.amount}`)
}
}
}
const exampleWithPaymentObserver = (builder: SdkBuilder): SdkBuilder => {
const paymentObserver = new ExamplePaymentObserver()
return builder.withPaymentObserver(paymentObserver)
}
class ExamplePaymentObserver {
beforeSend = async (payments: ProvisionalPayment[]) => {
for (const payment of payments) {
console.log(`About to send payment: ${payment.paymentId} of amount ${payment.amount}`)
}
}
}
const exampleWithPaymentObserver = async (builder: SdkBuilder) => {
const paymentObserver = new ExamplePaymentObserver()
await builder.withPaymentObserver(paymentObserver)
}
class ExamplePaymentObserver(PaymentObserver):
def before_send(self, payments: typing.List[ProvisionalPayment]):
for payment in payments:
logging.debug(f"About to send payment {payment.payment_id} of amount {payment.amount}")
async def with_payment_observer(builder: SdkBuilder):
payment_observer = ExamplePaymentObserver()
await builder.with_payment_observer(payment_observer=payment_observer)
type ExamplePaymentObserver struct{}
func (ExamplePaymentObserver) BeforeSend(payments []breez_sdk_spark.ProvisionalPayment) error {
for _, payment := range payments {
log.Printf("About to send payment: %v of amount %v", payment.PaymentId, payment.Amount)
}
return nil
}
func WithPaymentObserver(builder *breez_sdk_spark.SdkBuilder) {
observer := ExamplePaymentObserver{}
builder.WithPaymentObserver(observer)
}