breez_sdk_spark/
sdk_builder.rs

1#![cfg_attr(
2    all(target_family = "wasm", target_os = "unknown"),
3    allow(clippy::arc_with_non_send_sync)
4)]
5use std::sync::Arc;
6
7use breez_sdk_common::rest::{ReqwestRestClient as CommonRequestRestClient, RestClient};
8use spark_wallet::DefaultSigner;
9use tokio::sync::watch;
10
11use crate::{
12    Credentials, Network,
13    chain::{
14        BitcoinChainService,
15        rest_client::{BasicAuth, RestClientChainService},
16    },
17    error::SdkError,
18    models::Config,
19    persist::Storage,
20    sdk::BreezSdk,
21};
22
23/// Builder for creating `BreezSdk` instances with customizable components.
24#[derive(Clone)]
25pub struct SdkBuilder {
26    config: Config,
27    mnemonic: String,
28    storage: Arc<dyn Storage>,
29    chain_service: Option<Arc<dyn BitcoinChainService>>,
30    lnurl_client: Option<Arc<dyn RestClient>>,
31}
32
33impl SdkBuilder {
34    /// Creates a new `SdkBuilder` with the provided configuration.
35    /// Arguments:
36    /// - `config`: The configuration to be used.
37    /// - `mnemonic`: The mnemonic phrase for the wallet.
38    /// - `storage`: The storage backend to be used.
39    pub fn new(config: Config, mnemonic: String, storage: Arc<dyn Storage>) -> Self {
40        SdkBuilder {
41            config,
42            mnemonic,
43            storage,
44            chain_service: None,
45            lnurl_client: None,
46        }
47    }
48
49    /// Sets the chain service to be used by the SDK.
50    /// Arguments:
51    /// - `chain_service`: The chain service to be used.
52    #[must_use]
53    pub fn with_chain_service(mut self, chain_service: Arc<dyn BitcoinChainService>) -> Self {
54        self.chain_service = Some(chain_service);
55        self
56    }
57
58    /// Sets the REST chain service to be used by the SDK.
59    /// Arguments:
60    /// - `url`: The base URL of the REST API.
61    /// - `credentials`: Optional credentials for basic authentication.
62    #[must_use]
63    pub fn with_rest_chain_service(
64        mut self,
65        url: String,
66        credentials: Option<Credentials>,
67    ) -> Self {
68        self.chain_service = Some(Arc::new(RestClientChainService::new(
69            url,
70            self.config.network,
71            5,
72            Box::new(CommonRequestRestClient::new().unwrap()),
73            credentials.map(|c| BasicAuth::new(c.username, c.password)),
74        )));
75        self
76    }
77
78    #[must_use]
79    pub fn with_lnurl_client(mut self, lnurl_client: Arc<dyn RestClient>) -> Self {
80        self.lnurl_client = Some(lnurl_client);
81        self
82    }
83
84    /// Builds the `BreezSdk` instance with the configured components.
85    pub async fn build(self) -> Result<BreezSdk, SdkError> {
86        // Create the signer from mnemonic
87        let mnemonic =
88            bip39::Mnemonic::parse(&self.mnemonic).map_err(|e| SdkError::Generic(e.to_string()))?;
89        let signer = DefaultSigner::new(&mnemonic.to_seed(""), self.config.network.into())
90            .map_err(|e| SdkError::Generic(e.to_string()))?;
91        let chain_service = if let Some(service) = self.chain_service {
92            service
93        } else {
94            let inner_client =
95                CommonRequestRestClient::new().map_err(|e| SdkError::Generic(e.to_string()))?;
96            match self.config.network {
97                Network::Mainnet => Arc::new(RestClientChainService::new(
98                    "https://blockstream.info/api".to_string(),
99                    self.config.network,
100                    5,
101                    Box::new(inner_client),
102                    None,
103                )),
104                Network::Regtest => Arc::new(RestClientChainService::new(
105                    "https://regtest-mempool.loadtest.dev.sparkinfra.net/api".to_string(),
106                    self.config.network,
107                    5,
108                    Box::new(inner_client),
109                    match (
110                        std::env::var("CHAIN_SERVICE_USERNAME"),
111                        std::env::var("CHAIN_SERVICE_PASSWORD"),
112                    ) {
113                        (Ok(username), Ok(password)) => Some(BasicAuth::new(username, password)),
114                        _ => None,
115                    },
116                )),
117            }
118        };
119        let lnurl_client: Arc<dyn RestClient> = match self.lnurl_client {
120            Some(client) => client,
121            None => Arc::new(
122                CommonRequestRestClient::new().map_err(|e| SdkError::Generic(e.to_string()))?,
123            ),
124        };
125        let (shutdown_sender, shutdown_receiver) = watch::channel::<()>(());
126        // Create the SDK instance
127        let sdk = BreezSdk::new(
128            self.config,
129            signer,
130            self.storage,
131            chain_service,
132            lnurl_client,
133            shutdown_sender,
134            shutdown_receiver,
135        )
136        .await?;
137
138        sdk.start();
139        Ok(sdk)
140    }
141}