1use std::sync::{Arc, Mutex};
2
3use lwk_wollet::clients::blocking::{self, BlockchainBackend};
4
5use crate::{BlockHeader, LwkError, Network, Transaction, Txid, Update, Wollet};
6
7#[derive(uniffi::Object, Debug)]
12pub struct EsploraClient {
13 pub(crate) inner: Mutex<blocking::EsploraClient>,
14}
15
16#[derive(uniffi::Record)]
18pub struct EsploraClientBuilder {
19 base_url: String,
20 network: Arc<Network>,
21 #[uniffi(default = false)]
22 waterfalls: bool,
23 #[uniffi(default = None)]
24 concurrency: Option<u32>,
25 #[uniffi(default = None)]
26 timeout: Option<u8>,
27 #[uniffi(default = false)]
28 utxo_only: bool,
29}
30
31impl From<EsploraClientBuilder> for lwk_wollet::clients::EsploraClientBuilder {
32 fn from(builder: EsploraClientBuilder) -> Self {
33 let mut result = lwk_wollet::clients::EsploraClientBuilder::new(
34 &builder.base_url,
35 (*builder.network.as_ref()).into(),
36 );
37 if builder.waterfalls {
38 result = result.waterfalls(true);
39 }
40 if let Some(concurrency) = builder.concurrency {
41 result = result.concurrency(concurrency as usize);
42 }
43 if let Some(timeout) = builder.timeout {
44 result = result.timeout(timeout);
45 }
46 if builder.utxo_only {
47 result = result.utxo_only(true);
48 }
49 result
50 }
51}
52
53#[uniffi::export]
54impl EsploraClient {
55 #[uniffi::constructor]
57 pub fn new(url: &str, network: &Network) -> Result<Arc<Self>, LwkError> {
58 let client = blocking::EsploraClient::new(url, network.into())?;
59 Ok(Arc::new(Self {
60 inner: Mutex::new(client),
61 }))
62 }
63
64 #[uniffi::constructor]
66 pub fn new_waterfalls(url: &str, network: &Network) -> Result<Arc<Self>, LwkError> {
67 let client = blocking::EsploraClient::new_waterfalls(url, network.into())?;
68 Ok(Arc::new(Self {
69 inner: Mutex::new(client),
70 }))
71 }
72
73 #[uniffi::constructor]
75 pub fn from_builder(builder: EsploraClientBuilder) -> Result<Arc<Self>, LwkError> {
76 Ok(Arc::new(Self {
77 inner: Mutex::new(
78 lwk_wollet::clients::EsploraClientBuilder::from(builder).build_blocking()?,
79 ),
80 }))
81 }
82
83 pub fn broadcast(&self, tx: &Transaction) -> Result<Arc<Txid>, LwkError> {
85 Ok(Arc::new(self.inner.lock()?.broadcast(tx.as_ref())?.into()))
86 }
87
88 pub fn full_scan(&self, wollet: &Wollet) -> Result<Option<Arc<Update>>, LwkError> {
99 self.full_scan_to_index(wollet, 0)
100 }
101
102 pub fn full_scan_to_index(
115 &self,
116 wollet: &Wollet,
117 index: u32,
118 ) -> Result<Option<Arc<Update>>, LwkError> {
119 let wollet = wollet.inner_wollet()?;
120 let update: Option<lwk_wollet::Update> = self
121 .inner
122 .lock()?
123 .full_scan_to_index(&wollet.state(), index)?;
124 Ok(update.map(Into::into).map(Arc::new))
125 }
126
127 pub fn tip(&self) -> Result<Arc<BlockHeader>, LwkError> {
129 let tip = self.inner.lock()?.tip()?;
130 Ok(Arc::new(tip.into()))
131 }
132}