14
14
use std:: collections:: HashMap ;
15
15
use std:: marker:: PhantomData ;
16
16
use std:: str:: FromStr ;
17
+ use std:: time:: Duration ; //-----------------------added----------------
18
+ use std:: convert:: TryInto ; //-------------------added-----------------
17
19
18
20
use bitcoin:: consensus:: { deserialize, serialize, Decodable , Encodable } ;
19
21
use bitcoin:: hashes:: { sha256, Hash } ;
@@ -26,71 +28,96 @@ use bitcoin::{
26
28
#[ allow( unused_imports) ]
27
29
use log:: { debug, error, info, trace} ;
28
30
29
- use reqwest:: { header, Client , Response } ;
30
-
31
+ // use reqwest::{header, Client, Response};
32
+ use async_minreq :: { Method , Request } ; //-----------------------added-------------------
31
33
use crate :: api:: AddressStats ;
32
34
use crate :: {
33
35
BlockStatus , BlockSummary , Builder , Error , MerkleProof , OutputStatus , Tx , TxStatus ,
34
36
BASE_BACKOFF_MILLIS , RETRYABLE_ERROR_CODES ,
35
37
} ;
36
38
39
+ // #[derive(Debug, Clone)]
40
+ // pub struct AsyncClient<S = DefaultSleeper> {
41
+ // /// The URL of the Esplora Server.
42
+ // url: String,
43
+ // /// The inner [`reqwest::Client`] to make HTTP requests.
44
+ // client: Client,
45
+ // /// Number of times to retry a request
46
+ // max_retries: usize,
47
+
48
+ // /// Marker for the type of sleeper used
49
+ // marker: PhantomData<S>,
50
+ // }
51
+
37
52
#[ derive( Debug , Clone ) ]
38
53
pub struct AsyncClient < S = DefaultSleeper > {
39
- /// The URL of the Esplora Server .
54
+ /// The base URL of the Esplora server .
40
55
url : String ,
41
- /// The inner [`reqwest::Client`] to make HTTP requests.
42
- client : Client ,
43
- /// Number of times to retry a request
56
+ /// Number of times to retry a request.
44
57
max_retries : usize ,
45
-
46
- /// Marker for the type of sleeper used
58
+ /// Default headers (applied to every request).
59
+ headers : HashMap < String , String > ,
60
+ /// Marker for the sleeper.
47
61
marker : PhantomData < S > ,
48
62
}
49
63
50
64
impl < S : Sleeper > AsyncClient < S > {
51
65
/// Build an async client from a builder
52
66
pub fn from_builder ( builder : Builder ) -> Result < Self , Error > {
53
- let mut client_builder = Client :: builder ( ) ;
54
-
55
- #[ cfg( not( target_arch = "wasm32" ) ) ]
56
- if let Some ( proxy) = & builder. proxy {
57
- client_builder = client_builder. proxy ( reqwest:: Proxy :: all ( proxy) ?) ;
58
- }
59
67
60
- #[ cfg( not( target_arch = "wasm32" ) ) ]
61
- if let Some ( timeout) = builder. timeout {
62
- client_builder = client_builder. timeout ( core:: time:: Duration :: from_secs ( timeout) ) ;
63
- }
64
-
65
- if !builder. headers . is_empty ( ) {
66
- let mut headers = header:: HeaderMap :: new ( ) ;
67
- for ( k, v) in builder. headers {
68
- let header_name = header:: HeaderName :: from_lowercase ( k. to_lowercase ( ) . as_bytes ( ) )
69
- . map_err ( |_| Error :: InvalidHttpHeaderName ( k) ) ?;
70
- let header_value = header:: HeaderValue :: from_str ( & v)
71
- . map_err ( |_| Error :: InvalidHttpHeaderValue ( v) ) ?;
72
- headers. insert ( header_name, header_value) ;
73
- }
74
- client_builder = client_builder. default_headers ( headers) ;
75
- }
76
-
77
- Ok ( AsyncClient {
68
+ //----------------------------------------not needed since no client struct in async minreq------------------------------------
69
+ // let mut client_builder = Client::builder();
70
+
71
+ // #[cfg(not(target_arch = "wasm32"))]
72
+ // if let Some(proxy) = &builder.proxy {
73
+ // client_builder = client_builder.proxy(reqwest::Proxy::all(proxy)?);
74
+ // }
75
+
76
+ // #[cfg(not(target_arch = "wasm32"))]
77
+ // if let Some(timeout) = builder.timeout {
78
+ // client_builder = client_builder.timeout(core::time::Duration::from_secs(timeout));
79
+ // }
80
+
81
+ // if !builder.headers.is_empty() {
82
+ // let mut headers = header::HeaderMap::new();
83
+ // for (k, v) in builder.headers {
84
+ // let header_name = header::HeaderName::from_lowercase(k.to_lowercase().as_bytes())
85
+ // .map_err(|_| Error::InvalidHttpHeaderName(k))?;
86
+ // let header_value = header::HeaderValue::from_str(&v)
87
+ // .map_err(|_| Error::InvalidHttpHeaderValue(v))?;
88
+ // headers.insert(header_name, header_value);
89
+ // }
90
+ // client_builder = client_builder.default_headers(headers);
91
+ // }
92
+
93
+ // Ok(AsyncClient {
94
+ // url: builder.base_url,
95
+ // client: client_builder.build()?,
96
+ // max_retries: builder.max_retries,
97
+ // marker: PhantomData,
98
+ // })
99
+
100
+ //--------------------------------------------------------------------------------------
101
+ Ok ( AsyncClient {
78
102
url : builder. base_url ,
79
- client : client_builder. build ( ) ?,
80
103
max_retries : builder. max_retries ,
104
+ headers : builder. headers ,
81
105
marker : PhantomData ,
82
106
} )
83
- }
84
107
85
- pub fn from_client ( url : String , client : Client ) -> Self {
86
- AsyncClient {
87
- url,
88
- client,
89
- max_retries : crate :: DEFAULT_MAX_RETRIES ,
90
- marker : PhantomData ,
91
- }
108
+
92
109
}
93
110
111
+ //----------------------------------------not needed since no client struct in async minreq------------------------------------
112
+ // pub fn from_client(url: String, client: Client) -> Self {
113
+ // AsyncClient {
114
+ // url,
115
+ // client,
116
+ // max_retries: crate::DEFAULT_MAX_RETRIES,
117
+ // marker: PhantomData,
118
+ // }
119
+ // }
120
+ //-----------------------------------------------------------------------------------------------
94
121
/// Make an HTTP GET request to given URL, deserializing to any `T` that
95
122
/// implement [`bitcoin::consensus::Decodable`].
96
123
///
@@ -106,14 +133,14 @@ impl<S: Sleeper> AsyncClient<S> {
106
133
let url = format ! ( "{}{}" , self . url, path) ;
107
134
let response = self . get_with_retry ( & url) . await ?;
108
135
109
- if !response. status ( ) . is_success ( ) {
136
+ if !( response. status_code == 200 ) {
110
137
return Err ( Error :: HttpResponse {
111
- status : response. status ( ) . as_u16 ( ) ,
112
- message : response. text ( ) . await ? ,
138
+ status : response. status_code as u16 ,
139
+ message : response. as_str ( ) . unwrap ( ) . to_string ( ) ,
113
140
} ) ;
114
141
}
115
142
116
- Ok ( deserialize :: < T > ( & response. bytes ( ) . await ? ) ?)
143
+ Ok ( deserialize :: < T > ( & response. as_bytes ( ) ) ?)
117
144
}
118
145
119
146
/// Make an HTTP GET request to given URL, deserializing to `Option<T>`.
@@ -146,14 +173,14 @@ impl<S: Sleeper> AsyncClient<S> {
146
173
let url = format ! ( "{}{}" , self . url, path) ;
147
174
let response = self . get_with_retry ( & url) . await ?;
148
175
149
- if !response. status ( ) . is_success ( ) {
176
+ if !( response. status_code == 200 ) {
150
177
return Err ( Error :: HttpResponse {
151
- status : response. status ( ) . as_u16 ( ) ,
152
- message : response. text ( ) . await ? ,
178
+ status : response. status_code as u16 ,
179
+ message : response. as_str ( ) . unwrap ( ) . to_string ( ) ,
153
180
} ) ;
154
181
}
155
182
156
- response . json :: < T > ( ) . await . map_err ( Error :: Reqwest )
183
+ serde_json :: from_str ( & response . as_str ( ) . unwrap ( ) . to_string ( ) ) . map_err ( Error :: Json )
157
184
}
158
185
159
186
/// Make an HTTP GET request to given URL, deserializing to `Option<T>`.
@@ -188,14 +215,14 @@ impl<S: Sleeper> AsyncClient<S> {
188
215
let url = format ! ( "{}{}" , self . url, path) ;
189
216
let response = self . get_with_retry ( & url) . await ?;
190
217
191
- if !response. status ( ) . is_success ( ) {
218
+ if !( response. status_code == 200 ) {
192
219
return Err ( Error :: HttpResponse {
193
- status : response. status ( ) . as_u16 ( ) ,
194
- message : response. text ( ) . await ? ,
220
+ status : response. status_code as u16 ,
221
+ message : response. as_str ( ) . unwrap ( ) . to_string ( ) ,
195
222
} ) ;
196
223
}
197
224
198
- let hex_str = response. text ( ) . await ? ;
225
+ let hex_str =response. as_str ( ) . unwrap ( ) . to_string ( ) ;
199
226
Ok ( deserialize ( & Vec :: from_hex ( & hex_str) ?) ?)
200
227
}
201
228
@@ -225,14 +252,14 @@ impl<S: Sleeper> AsyncClient<S> {
225
252
let url = format ! ( "{}{}" , self . url, path) ;
226
253
let response = self . get_with_retry ( & url) . await ?;
227
254
228
- if !response. status ( ) . is_success ( ) {
255
+ if !( response. status_code == 200 ) {
229
256
return Err ( Error :: HttpResponse {
230
- status : response. status ( ) . as_u16 ( ) ,
231
- message : response. text ( ) . await ? ,
257
+ status : response. status_code as u16 ,
258
+ message : response. as_str ( ) . unwrap ( ) . to_string ( ) ,
232
259
} ) ;
233
260
}
234
-
235
- Ok ( response. text ( ) . await ? )
261
+ // let x=response.as_str().unwrap().to_string();
262
+ Ok ( response. as_str ( ) . unwrap ( ) . to_string ( ) )
236
263
}
237
264
238
265
/// Make an HTTP GET request to given URL, deserializing to `Option<T>`.
@@ -263,15 +290,12 @@ impl<S: Sleeper> AsyncClient<S> {
263
290
let url = format ! ( "{}{}" , self . url, path) ;
264
291
let body = serialize :: < T > ( & body) . to_lower_hex_string ( ) ;
265
292
266
- let response = self . client . post ( url) . body ( body) . send ( ) . await ?;
267
-
268
- if !response. status ( ) . is_success ( ) {
269
- return Err ( Error :: HttpResponse {
270
- status : response. status ( ) . as_u16 ( ) ,
271
- message : response. text ( ) . await ?,
272
- } ) ;
293
+ let mut request = Request :: new ( Method :: Post , & url) . with_body ( body) ;
294
+ for ( key, value) in & self . headers {
295
+ request = request. with_header ( key, value) ;
273
296
}
274
-
297
+
298
+ let _ = request. send ( ) . await . map_err ( Error :: AsyncMinreq ) ?;
275
299
Ok ( ( ) )
276
300
}
277
301
@@ -284,7 +308,7 @@ impl<S: Sleeper> AsyncClient<S> {
284
308
pub async fn get_tx_no_opt ( & self , txid : & Txid ) -> Result < Transaction , Error > {
285
309
match self . get_tx ( txid) . await {
286
310
Ok ( Some ( tx) ) => Ok ( tx) ,
287
- Ok ( None ) => Err ( Error :: TransactionNotFound ( * txid) ) ,
311
+ Ok ( None ) => Err ( Error :: TransactionNotFound ( * txid) ) , //look into
288
312
Err ( e) => Err ( e) ,
289
313
}
290
314
}
@@ -455,32 +479,52 @@ impl<S: Sleeper> AsyncClient<S> {
455
479
}
456
480
457
481
/// Get the underlying [`Client`].
458
- pub fn client ( & self ) -> & Client {
459
- & self . client
460
- }
482
+ // pub fn client(&self) -> &Client {
483
+ // &self.client
484
+ // }
461
485
462
486
/// Sends a GET request to the given `url`, retrying failed attempts
463
487
/// for retryable error codes until max retries hit.
464
- async fn get_with_retry ( & self , url : & str ) -> Result < Response , Error > {
488
+ async fn get_with_retry ( & self , url : & str ) -> Result < async_minreq :: Response , Error > {
465
489
let mut delay = BASE_BACKOFF_MILLIS ;
466
490
let mut attempts = 0 ;
467
491
468
492
loop {
469
- match self . client . get ( url) . send ( ) . await ? {
470
- resp if attempts < self . max_retries && is_status_retryable ( resp. status ( ) ) => {
471
- S :: sleep ( delay) . await ;
472
- attempts += 1 ;
473
- delay *= 2 ;
493
+ let mut request = Request :: new ( Method :: Get , url) ;
494
+ // Apply headers from the builder.
495
+ for ( key, value) in & self . headers {
496
+ request = request. with_header ( key, value) ;
497
+ }
498
+ // request.
499
+
500
+ let res = request. send ( ) . await . map_err ( Error :: AsyncMinreq ) ;
501
+
502
+ match res {
503
+ Ok ( body) => {
504
+
505
+
506
+ return Ok ( body) ;
507
+
508
+ } ,
509
+ Err ( e) => {
510
+ // Here you might inspect the error (if possible) to decide whether to retry.
511
+ // For simplicity, we retry on any error until max_retries is reached.
512
+ if attempts < self . max_retries {
513
+ S :: sleep ( delay) . await ;
514
+ attempts += 1 ;
515
+ delay *= 2 ;
516
+ continue ;
517
+ }
518
+ return Err ( e) ;
474
519
}
475
- resp => return Ok ( resp) ,
476
520
}
477
521
}
478
522
}
479
523
}
480
524
481
- fn is_status_retryable ( status : reqwest:: StatusCode ) -> bool {
482
- RETRYABLE_ERROR_CODES . contains ( & status. as_u16 ( ) )
483
- }
525
+ // fn is_status_retryable(status: reqwest::StatusCode) -> bool {
526
+ // RETRYABLE_ERROR_CODES.contains(&status.as_u16())
527
+ // }
484
528
485
529
pub trait Sleeper : ' static {
486
530
type Sleep : std:: future:: Future < Output = ( ) > ;
0 commit comments