1use std::future::Future;
14use std::sync::Arc;
15
16use crate::frb_generated::StreamSink;
17use crate::lnurl::pay::LnUrlPayResult;
18use anyhow::{anyhow, Result};
19use log::{Level, LevelFilter, Metadata, Record};
20use once_cell::sync::{Lazy, OnceCell};
21use sdk_common::invoice;
22pub use sdk_common::prelude::{
23 parse, AesSuccessActionDataDecrypted, AesSuccessActionDataResult, BitcoinAddressData,
24 CurrencyInfo, FiatCurrency, InputType, LNInvoice, LnUrlAuthRequestData, LnUrlCallbackStatus,
25 LnUrlError, LnUrlErrorData, LnUrlPayErrorData, LnUrlPayRequest, LnUrlPayRequestData,
26 LnUrlWithdrawRequest, LnUrlWithdrawRequestData, LnUrlWithdrawResult, LnUrlWithdrawSuccessData,
27 LocaleOverrides, LocalizedName, MessageSuccessActionData, Network, Rate, RouteHint,
28 RouteHintHop, SuccessActionProcessed, Symbol, UrlSuccessActionData,
29};
30use sdk_common::prelude::{LnUrlPayError, LnUrlWithdrawError};
31use tokio::sync::Mutex;
32
33use crate::breez_services::{self, BreezEvent, BreezServices, EventListener};
34use crate::chain::RecommendedFees;
35use crate::error::{
36 ConnectError, ReceiveOnchainError, ReceivePaymentError, RedeemOnchainError, SdkError,
37 SendOnchainError, SendPaymentError,
38};
39use crate::lsp::LspInformation;
40use crate::models::{Config, LogEntry, NodeState, Payment, SwapInfo};
41use crate::{
42 BackupStatus, BuyBitcoinRequest, BuyBitcoinResponse, CheckMessageRequest, CheckMessageResponse,
43 ConfigureNodeRequest, ConnectRequest, EnvironmentType, ListPaymentsRequest, ListSwapsRequest,
44 LnUrlAuthError, NodeConfig, NodeCredentials, OnchainPaymentLimitsResponse,
45 OpenChannelFeeRequest, OpenChannelFeeResponse, PayOnchainRequest, PayOnchainResponse,
46 PrepareOnchainPaymentRequest, PrepareOnchainPaymentResponse, PrepareRedeemOnchainFundsRequest,
47 PrepareRedeemOnchainFundsResponse, PrepareRefundRequest, PrepareRefundResponse,
48 ReceiveOnchainRequest, ReceivePaymentRequest, ReceivePaymentResponse,
49 RedeemOnchainFundsRequest, RedeemOnchainFundsResponse, RefundRequest, RefundResponse,
50 ReportIssueRequest, ReverseSwapFeesRequest, ReverseSwapInfo, ReverseSwapPairInfo,
51 SendPaymentRequest, SendPaymentResponse, SendSpontaneousPaymentRequest,
52 ServiceHealthCheckResponse, SignMessageRequest, SignMessageResponse, StaticBackupRequest,
53 StaticBackupResponse,
54};
55
56use flutter_rust_bridge::frb;
64
65#[frb(mirror(LnUrlAuthRequestData))]
66pub struct _LnUrlAuthRequestData {
67 pub k1: String,
68 pub action: Option<String>,
69 pub domain: String,
70 pub url: String,
71}
72
73#[frb(mirror(LnUrlErrorData))]
74pub struct _LnUrlErrorData {
75 pub reason: String,
76}
77
78#[frb(mirror(LnUrlCallbackStatus))]
79pub enum _LnUrlCallbackStatus {
80 Ok,
81 ErrorStatus { data: LnUrlErrorData },
82}
83
84#[frb(mirror(Network))]
85pub enum _Network {
86 Bitcoin,
87 Testnet,
88 Signet,
89 Regtest,
90}
91
92#[frb(mirror(LNInvoice))]
93pub struct _LNInvoice {
94 pub bolt11: String,
95 pub network: Network,
96 pub payee_pubkey: String,
97 pub payment_hash: String,
98 pub description: Option<String>,
99 pub description_hash: Option<String>,
100 pub amount_msat: Option<u64>,
101 pub timestamp: u64,
102 pub expiry: u64,
103 pub routing_hints: Vec<RouteHint>,
104 pub payment_secret: Vec<u8>,
105 pub min_final_cltv_expiry_delta: u64,
106}
107
108#[frb(mirror(RouteHint))]
109pub struct _RouteHint {
110 pub hops: Vec<RouteHintHop>,
111}
112
113#[frb(mirror(RouteHintHop))]
114pub struct _RouteHintHop {
115 pub src_node_id: String,
116 pub short_channel_id: String,
117 pub fees_base_msat: u32,
118 pub fees_proportional_millionths: u32,
119 pub cltv_expiry_delta: u64,
120 pub htlc_minimum_msat: Option<u64>,
121 pub htlc_maximum_msat: Option<u64>,
122}
123
124#[frb(mirror(LnUrlPayRequest))]
125pub struct _LnUrlPayRequest {
126 pub data: LnUrlPayRequestData,
127 pub amount_msat: u64,
128 pub use_trampoline: bool,
129 pub comment: Option<String>,
130 pub payment_label: Option<String>,
131 pub validate_success_action_url: Option<bool>,
132}
133
134#[frb(mirror(LnUrlPayRequestData))]
135pub struct _LnUrlPayRequestData {
136 pub callback: String,
137 pub min_sendable: u64,
138 pub max_sendable: u64,
139 pub metadata_str: String,
140 pub comment_allowed: u16,
141 pub domain: String,
142 pub allows_nostr: bool,
143 pub nostr_pubkey: Option<String>,
144 pub ln_address: Option<String>,
145}
146
147#[frb(mirror(LnUrlWithdrawRequest))]
148pub struct _LnUrlWithdrawRequest {
149 pub data: LnUrlWithdrawRequestData,
150 pub amount_msat: u64,
151 pub description: Option<String>,
152}
153
154#[frb(mirror(LnUrlWithdrawRequestData))]
155pub struct _LnUrlWithdrawRequestData {
156 pub callback: String,
157 pub k1: String,
158 pub default_description: String,
159 pub min_withdrawable: u64,
160 pub max_withdrawable: u64,
161}
162
163#[frb(mirror(InputType))]
164pub enum _InputType {
165 BitcoinAddress {
166 address: BitcoinAddressData,
167 },
168 Bolt11 {
169 invoice: LNInvoice,
170 },
171 NodeId {
172 node_id: String,
173 },
174 Url {
175 url: String,
176 },
177 LnUrlPay {
178 data: LnUrlPayRequestData,
179 bip353_address: Option<String>,
180 },
181 LnUrlWithdraw {
182 data: LnUrlWithdrawRequestData,
183 },
184 LnUrlAuth {
185 data: LnUrlAuthRequestData,
186 },
187 LnUrlError {
188 data: LnUrlErrorData,
189 },
190}
191
192#[frb(mirror(BitcoinAddressData))]
193pub struct _BitcoinAddressData {
194 pub address: String,
195 pub network: Network,
196 pub amount_sat: Option<u64>,
197 pub label: Option<String>,
198 pub message: Option<String>,
199}
200
201#[frb(mirror(SuccessActionProcessed))]
202pub enum _SuccessActionProcessed {
203 Aes { result: AesSuccessActionDataResult },
204 Message { data: MessageSuccessActionData },
205 Url { data: UrlSuccessActionData },
206}
207
208#[frb(mirror(AesSuccessActionDataResult))]
209pub enum _AesSuccessActionDataResult {
210 Decrypted { data: AesSuccessActionDataDecrypted },
211 ErrorStatus { reason: String },
212}
213
214#[frb(mirror(AesSuccessActionDataDecrypted))]
215pub struct _AesSuccessActionDataDecrypted {
216 pub description: String,
217 pub plaintext: String,
218}
219
220#[frb(mirror(MessageSuccessActionData))]
221pub struct _MessageSuccessActionData {
222 pub message: String,
223}
224
225#[frb(mirror(UrlSuccessActionData))]
226pub struct _UrlSuccessActionData {
227 pub description: String,
228 pub url: String,
229 pub matches_callback_domain: bool,
230}
231
232#[frb(mirror(LnUrlPayErrorData))]
233pub struct _LnUrlPayErrorData {
234 pub payment_hash: String,
235 pub reason: String,
236}
237
238#[frb(mirror(LnUrlPayError))]
239pub enum _LnUrlPayError {
240 AlreadyPaid,
241 Generic { err: String },
242 InvalidAmount { err: String },
243 InvalidInvoice { err: String },
244 InvalidNetwork { err: String },
245 InvalidUri { err: String },
246 InvoiceExpired { err: String },
247 PaymentFailed { err: String },
248 PaymentTimeout { err: String },
249 RouteNotFound { err: String },
250 RouteTooExpensive { err: String },
251 ServiceConnectivity { err: String },
252}
253
254#[frb(mirror(LnUrlWithdrawResult))]
255pub enum _LnUrlWithdrawResult {
256 Ok { data: LnUrlWithdrawSuccessData },
257 Timeout { data: LnUrlWithdrawSuccessData },
258 ErrorStatus { data: LnUrlErrorData },
259}
260
261#[frb(mirror(LnUrlWithdrawSuccessData))]
262pub struct _LnUrlWithdrawSuccessData {
263 pub invoice: LNInvoice,
264}
265
266#[frb(mirror(Rate))]
267pub struct _Rate {
268 pub coin: String,
269 pub value: f64,
270}
271
272#[frb(mirror(FiatCurrency))]
273pub struct _FiatCurrency {
274 pub id: String,
275 pub info: CurrencyInfo,
276}
277
278#[frb(mirror(CurrencyInfo))]
279pub struct _CurrencyInfo {
280 pub name: String,
281 pub fraction_size: u32,
282 pub spacing: Option<u32>,
283 pub symbol: Option<Symbol>,
284 pub uniq_symbol: Option<Symbol>,
285 pub localized_name: Vec<LocalizedName>,
286 pub locale_overrides: Vec<LocaleOverrides>,
287}
288
289#[frb(mirror(LocaleOverrides))]
290pub struct _LocaleOverrides {
291 pub locale: String,
292 pub spacing: Option<u32>,
293 pub symbol: Symbol,
294}
295
296#[frb(mirror(LocalizedName))]
297pub struct _LocalizedName {
298 pub locale: String,
299 pub name: String,
300}
301
302#[frb(mirror(Symbol))]
303pub struct _Symbol {
304 pub grapheme: Option<String>,
305 pub template: Option<String>,
306 pub rtl: Option<bool>,
307 pub position: Option<u32>,
308}
309
310static BREEZ_SERVICES_INSTANCE: Lazy<Mutex<Option<Arc<BreezServices>>>> =
315 Lazy::new(|| Mutex::new(None));
316static NOTIFICATION_STREAM: OnceCell<StreamSink<BreezEvent>> = OnceCell::new();
317static RT: Lazy<tokio::runtime::Runtime> = Lazy::new(|| tokio::runtime::Runtime::new().unwrap());
318static LOG_INIT: OnceCell<bool> = OnceCell::new();
319
320pub fn connect(req: ConnectRequest) -> Result<()> {
324 block_on(async move {
325 let mut locked = BREEZ_SERVICES_INSTANCE.lock().await;
326 match *locked {
327 None => {
328 let breez_services =
329 BreezServices::connect(req, Box::new(BindingEventListener::new())).await?;
330
331 *locked = Some(breez_services);
332 Ok(())
333 }
334 Some(_) => Err(ConnectError::Generic {
335 err: "Static node services already set, please call disconnect() first".into(),
336 }),
337 }
338 })
339 .map_err(anyhow::Error::new::<ConnectError>)
340}
341
342pub fn is_initialized() -> bool {
344 block_on(async { get_breez_services().await.is_ok() })
345}
346
347#[frb(name = "sync")]
348pub fn sync() -> Result<()> {
350 block_on(async { get_breez_services().await?.sync().await })
351 .map_err(anyhow::Error::new::<SdkError>)
352}
353
354pub fn node_credentials() -> Result<Option<NodeCredentials>> {
356 block_on(async { get_breez_services().await?.node_credentials().await })
357 .map_err(anyhow::Error::new::<SdkError>)
358}
359
360pub fn node_info() -> Result<NodeState> {
362 block_on(async {
363 get_breez_services()
364 .await?
365 .node_info()
366 .map_err(anyhow::Error::new::<SdkError>)
367 })
368}
369
370pub fn configure_node(req: ConfigureNodeRequest) -> Result<()> {
372 block_on(async { get_breez_services().await?.configure_node(req).await })
373 .map_err(anyhow::Error::new::<SdkError>)
374}
375
376pub fn disconnect() -> Result<()> {
378 block_on(async {
379 get_breez_services().await?.disconnect().await?;
381 let mut locked_sdk_instance = BREEZ_SERVICES_INSTANCE.lock().await;
382 *locked_sdk_instance = None;
383
384 Ok(())
385 })
386 .map_err(anyhow::Error::new::<SdkError>)
387}
388
389pub fn sign_message(req: SignMessageRequest) -> Result<SignMessageResponse> {
391 block_on(async { get_breez_services().await?.sign_message(req).await })
392 .map_err(anyhow::Error::new::<SdkError>)
393}
394
395pub fn check_message(req: CheckMessageRequest) -> Result<CheckMessageResponse> {
397 block_on(async { get_breez_services().await?.check_message(req).await })
398 .map_err(anyhow::Error::new::<SdkError>)
399}
400
401pub fn mnemonic_to_seed(phrase: String) -> Result<Vec<u8>> {
405 breez_services::mnemonic_to_seed(phrase)
406}
407
408pub fn default_config(
410 env_type: EnvironmentType,
411 api_key: String,
412 node_config: NodeConfig,
413) -> Config {
414 BreezServices::default_config(env_type, api_key, node_config)
415}
416
417pub fn static_backup(req: StaticBackupRequest) -> Result<StaticBackupResponse> {
419 BreezServices::static_backup(req).map_err(anyhow::Error::new::<SdkError>)
420}
421
422pub fn service_health_check(api_key: String) -> Result<ServiceHealthCheckResponse> {
424 block_on(async { BreezServices::service_health_check(api_key).await })
425 .map_err(anyhow::Error::new::<SdkError>)
426}
427
428pub fn breez_events_stream(s: StreamSink<BreezEvent>) -> Result<()> {
432 NOTIFICATION_STREAM
433 .set(s)
434 .map_err(|_| anyhow!("Events stream already created"))?;
435 Ok(())
436}
437
438pub fn breez_log_stream(s: StreamSink<LogEntry>) -> Result<()> {
440 LOG_INIT
441 .set(true)
442 .map_err(|_| anyhow!("Log stream already created"))?;
443 BindingLogger::init(s);
444 Ok(())
445}
446
447pub fn list_lsps() -> Result<Vec<LspInformation>> {
451 block_on(async { get_breez_services().await?.list_lsps().await })
452 .map_err(anyhow::Error::new::<SdkError>)
453}
454
455pub fn connect_lsp(lsp_id: String) -> Result<()> {
457 block_on(async { get_breez_services().await?.connect_lsp(lsp_id).await })
458 .map_err(anyhow::Error::new::<SdkError>)
459}
460
461pub fn lsp_id() -> Result<Option<String>> {
463 block_on(async { get_breez_services().await?.lsp_id().await })
464 .map_err(anyhow::Error::new::<SdkError>)
465}
466
467pub fn fetch_lsp_info(id: String) -> Result<Option<LspInformation>> {
469 block_on(async { get_breez_services().await?.fetch_lsp_info(id).await })
470 .map_err(anyhow::Error::new::<SdkError>)
471}
472
473pub fn lsp_info() -> Result<LspInformation> {
475 block_on(async { get_breez_services().await?.lsp_info().await })
476 .map_err(anyhow::Error::new::<SdkError>)
477}
478
479pub fn close_lsp_channels() -> Result<()> {
481 block_on(async {
482 _ = get_breez_services().await?.close_lsp_channels().await?;
483 Ok(())
484 })
485}
486
487pub fn register_webhook(webhook_url: String) -> Result<()> {
488 block_on(async {
489 get_breez_services()
490 .await?
491 .register_webhook(webhook_url)
492 .await
493 })
494 .map_err(anyhow::Error::new::<SdkError>)
495}
496
497pub fn unregister_webhook(webhook_url: String) -> Result<()> {
498 block_on(async {
499 get_breez_services()
500 .await?
501 .unregister_webhook(webhook_url)
502 .await
503 })
504 .map_err(anyhow::Error::new::<SdkError>)
505}
506
507pub fn backup() -> Result<()> {
511 block_on(async { get_breez_services().await?.backup().await })
512 .map_err(anyhow::Error::new::<SdkError>)
513}
514
515pub fn backup_status() -> Result<BackupStatus> {
517 block_on(async { get_breez_services().await?.backup_status() })
518 .map_err(anyhow::Error::new::<SdkError>)
519}
520
521pub fn parse_invoice(invoice: String) -> Result<LNInvoice> {
524 invoice::parse_invoice(&invoice).map_err(|e| anyhow::Error::new::<SdkError>(e.into()))
525}
526
527pub fn parse_input(input: String) -> Result<InputType> {
528 block_on(async { parse(&input, None).await })
529}
530
531pub fn list_payments(req: ListPaymentsRequest) -> Result<Vec<Payment>> {
535 block_on(async { get_breez_services().await?.list_payments(req).await })
536 .map_err(anyhow::Error::new::<SdkError>)
537}
538
539pub fn payment_by_hash(hash: String) -> Result<Option<Payment>> {
541 block_on(async { get_breez_services().await?.payment_by_hash(hash).await })
542 .map_err(anyhow::Error::new::<SdkError>)
543}
544
545pub fn set_payment_metadata(hash: String, metadata: String) -> Result<()> {
547 block_on(async {
548 get_breez_services()
549 .await?
550 .set_payment_metadata(hash, metadata)
551 .await
552 })
553 .map_err(anyhow::Error::new::<SdkError>)
554}
555
556pub fn send_payment(req: SendPaymentRequest) -> Result<SendPaymentResponse> {
560 block_on(async { get_breez_services().await?.send_payment(req).await })
561 .map_err(anyhow::Error::new::<SendPaymentError>)
562}
563
564pub fn send_spontaneous_payment(req: SendSpontaneousPaymentRequest) -> Result<SendPaymentResponse> {
566 block_on(async {
567 get_breez_services()
568 .await?
569 .send_spontaneous_payment(req)
570 .await
571 })
572 .map_err(anyhow::Error::new::<SendPaymentError>)
573}
574
575pub fn receive_payment(req: ReceivePaymentRequest) -> Result<ReceivePaymentResponse> {
577 block_on(async { get_breez_services().await?.receive_payment(req).await })
578 .map_err(anyhow::Error::new::<ReceivePaymentError>)
579}
580
581pub fn lnurl_pay(req: LnUrlPayRequest) -> Result<LnUrlPayResult> {
585 block_on(async { get_breez_services().await?.lnurl_pay(req).await })
586 .map_err(anyhow::Error::new::<LnUrlPayError>)
587}
588
589pub fn lnurl_withdraw(req: LnUrlWithdrawRequest) -> Result<LnUrlWithdrawResult> {
591 block_on(async { get_breez_services().await?.lnurl_withdraw(req).await })
592 .map_err(anyhow::Error::new::<LnUrlWithdrawError>)
593}
594
595pub fn lnurl_auth(req_data: LnUrlAuthRequestData) -> Result<LnUrlCallbackStatus> {
597 block_on(async { get_breez_services().await?.lnurl_auth(req_data).await })
598 .map_err(anyhow::Error::new::<LnUrlAuthError>)
599}
600
601pub fn report_issue(req: ReportIssueRequest) -> Result<()> {
605 block_on(async { get_breez_services().await?.report_issue(req).await })
606 .map_err(anyhow::Error::new::<SdkError>)
607}
608
609pub fn fetch_fiat_rates() -> Result<Vec<Rate>> {
613 block_on(async { get_breez_services().await?.fetch_fiat_rates().await })
614 .map_err(anyhow::Error::new::<SdkError>)
615}
616
617pub fn list_fiat_currencies() -> Result<Vec<FiatCurrency>> {
619 block_on(async { get_breez_services().await?.list_fiat_currencies().await })
620 .map_err(anyhow::Error::new::<SdkError>)
621}
622
623pub fn pay_onchain(req: PayOnchainRequest) -> Result<PayOnchainResponse> {
627 block_on(async { get_breez_services().await?.pay_onchain(req).await })
628 .map_err(anyhow::Error::new::<SendOnchainError>)
629}
630
631pub fn receive_onchain(req: ReceiveOnchainRequest) -> Result<SwapInfo> {
633 block_on(async { get_breez_services().await?.receive_onchain(req).await })
634 .map_err(anyhow::Error::new::<ReceiveOnchainError>)
635}
636
637pub fn buy_bitcoin(req: BuyBitcoinRequest) -> Result<BuyBitcoinResponse> {
639 block_on(async { get_breez_services().await?.buy_bitcoin(req).await })
640 .map_err(anyhow::Error::new::<ReceiveOnchainError>)
641}
642
643pub fn redeem_onchain_funds(req: RedeemOnchainFundsRequest) -> Result<RedeemOnchainFundsResponse> {
645 block_on(async { get_breez_services().await?.redeem_onchain_funds(req).await })
646 .map_err(anyhow::Error::new::<RedeemOnchainError>)
647}
648
649pub fn prepare_redeem_onchain_funds(
651 req: PrepareRedeemOnchainFundsRequest,
652) -> Result<PrepareRedeemOnchainFundsResponse> {
653 block_on(async {
654 get_breez_services()
655 .await?
656 .prepare_redeem_onchain_funds(req)
657 .await
658 })
659 .map_err(anyhow::Error::new::<RedeemOnchainError>)
660}
661
662pub fn list_refundables() -> Result<Vec<SwapInfo>> {
666 block_on(async { get_breez_services().await?.list_refundables().await })
667 .map_err(anyhow::Error::new::<SdkError>)
668}
669
670pub fn prepare_refund(req: PrepareRefundRequest) -> Result<PrepareRefundResponse> {
672 block_on(async { get_breez_services().await?.prepare_refund(req).await })
673 .map_err(anyhow::Error::new::<SdkError>)
674}
675
676pub fn refund(req: RefundRequest) -> Result<RefundResponse> {
678 block_on(async { get_breez_services().await?.refund(req).await })
679 .map_err(anyhow::Error::new::<SdkError>)
680}
681
682pub fn rescan_swaps() -> Result<()> {
684 block_on(async { get_breez_services().await?.rescan_swaps().await })
685 .map_err(anyhow::Error::new::<SdkError>)
686}
687
688pub fn redeem_swap(swap_address: String) -> Result<()> {
690 block_on(async { get_breez_services().await?.redeem_swap(swap_address).await })
691 .map_err(anyhow::Error::new::<SdkError>)
692}
693
694pub fn in_progress_swap() -> Result<Option<SwapInfo>> {
698 block_on(async { get_breez_services().await?.in_progress_swap().await })
699 .map_err(anyhow::Error::new::<SdkError>)
700}
701
702pub fn list_swaps(req: ListSwapsRequest) -> Result<Vec<SwapInfo>> {
704 block_on(async { get_breez_services().await?.list_swaps(req).await })
705 .map_err(anyhow::Error::new::<SdkError>)
706}
707
708pub fn claim_reverse_swap(lockup_address: String) -> Result<()> {
710 block_on(async {
711 get_breez_services()
712 .await?
713 .claim_reverse_swap(lockup_address)
714 .await
715 })
716 .map_err(anyhow::Error::new::<SdkError>)
717}
718
719pub fn open_channel_fee(req: OpenChannelFeeRequest) -> Result<OpenChannelFeeResponse> {
723 block_on(async { get_breez_services().await?.open_channel_fee(req).await })
724 .map_err(anyhow::Error::new::<SdkError>)
725}
726
727pub fn fetch_reverse_swap_fees(req: ReverseSwapFeesRequest) -> Result<ReverseSwapPairInfo> {
729 block_on(async {
730 get_breez_services()
731 .await?
732 .fetch_reverse_swap_fees(req)
733 .await
734 })
735 .map_err(anyhow::Error::new::<SdkError>)
736}
737
738pub fn onchain_payment_limits() -> Result<OnchainPaymentLimitsResponse> {
740 block_on(async { get_breez_services().await?.onchain_payment_limits().await })
741 .map_err(anyhow::Error::new::<SdkError>)
742}
743
744pub fn prepare_onchain_payment(
746 req: PrepareOnchainPaymentRequest,
747) -> Result<PrepareOnchainPaymentResponse> {
748 block_on(async {
749 get_breez_services()
750 .await?
751 .prepare_onchain_payment(req)
752 .await
753 .map_err(anyhow::Error::new::<SendOnchainError>)
754 })
755}
756
757pub fn in_progress_onchain_payments() -> Result<Vec<ReverseSwapInfo>> {
759 block_on(async {
760 get_breez_services()
761 .await?
762 .in_progress_onchain_payments()
763 .await
764 })
765 .map_err(anyhow::Error::new::<SdkError>)
766}
767
768pub fn recommended_fees() -> Result<RecommendedFees> {
770 block_on(async { get_breez_services().await?.recommended_fees().await })
771 .map_err(anyhow::Error::new::<SdkError>)
772}
773
774pub fn execute_command(command: String) -> Result<String> {
778 block_on(async {
779 get_breez_services()
780 .await?
781 .execute_dev_command(command)
782 .await
783 })
784 .map_err(anyhow::Error::new::<SdkError>)
785}
786
787pub fn generate_diagnostic_data() -> Result<String> {
789 block_on(async { get_breez_services().await?.generate_diagnostic_data().await })
790 .map_err(anyhow::Error::new::<SdkError>)
791}
792
793pub struct BindingEventListener {}
796
797impl BindingEventListener {
798 fn new() -> Self {
799 Self {}
800 }
801}
802
803impl EventListener for BindingEventListener {
804 fn on_event(&self, e: BreezEvent) {
805 if let Some(stream) = NOTIFICATION_STREAM.get() {
806 let _ = stream.add(e);
807 }
808 }
809}
810
811struct BindingLogger {
812 log_stream: StreamSink<LogEntry>,
813}
814
815impl BindingLogger {
816 fn init(log_stream: StreamSink<LogEntry>) {
817 let binding_logger = BindingLogger { log_stream };
818 log::set_boxed_logger(Box::new(binding_logger)).unwrap();
819 log::set_max_level(LevelFilter::Trace);
820 }
821}
822
823impl log::Log for BindingLogger {
824 fn enabled(&self, m: &Metadata) -> bool {
825 m.level() <= Level::Trace
826 }
827
828 fn log(&self, record: &Record) {
829 if self.enabled(record.metadata()) {
830 let _ = self.log_stream.add(LogEntry {
831 line: record.args().to_string(),
832 level: record.level().as_str().to_string(),
833 });
834 }
835 }
836 fn flush(&self) {}
837}
838
839async fn get_breez_services() -> Result<Arc<BreezServices>, SdkError> {
840 match BREEZ_SERVICES_INSTANCE.lock().await.as_ref() {
841 None => Err(SdkError::Generic {
842 err: "Node service was not initialized".into(),
843 }),
844 Some(sdk) => Ok(sdk.clone()),
845 }
846}
847
848fn block_on<F: Future>(future: F) -> F::Output {
849 rt().block_on(future)
850}
851
852pub(crate) fn rt() -> &'static tokio::runtime::Runtime {
853 &RT
854}