@@ -31,8 +31,8 @@ use bitcoin::{
31
31
32
32
use crate :: api:: AddressStats ;
33
33
use crate :: {
34
- BlockStatus , BlockSummary , Builder , Error , MerkleProof , OutputStatus , Tx , TxStatus ,
35
- BASE_BACKOFF_MILLIS , RETRYABLE_ERROR_CODES ,
34
+ BlockStatus , BlockSummary , Builder , Error , MerkleProof , OutputStatus , SubmitPackageResult , Tx ,
35
+ TxStatus , BASE_BACKOFF_MILLIS , RETRYABLE_ERROR_CODES ,
36
36
} ;
37
37
38
38
#[ derive( Debug , Clone ) ]
@@ -88,6 +88,24 @@ impl BlockingClient {
88
88
Ok ( request)
89
89
}
90
90
91
+ fn post_request < T > ( & self , path : & str , body : T ) -> Result < Request , Error >
92
+ where
93
+ T : Into < Vec < u8 > > ,
94
+ {
95
+ let mut request = minreq:: post ( format ! ( "{}/{}" , self . url, path) ) . with_body ( body) ;
96
+
97
+ if let Some ( proxy) = & self . proxy {
98
+ let proxy = Proxy :: new ( proxy. as_str ( ) ) ?;
99
+ request = request. with_proxy ( proxy) ;
100
+ }
101
+
102
+ if let Some ( timeout) = & self . timeout {
103
+ request = request. with_timeout ( * timeout) ;
104
+ }
105
+
106
+ Ok ( request)
107
+ }
108
+
91
109
fn get_opt_response < T : Decodable > ( & self , path : & str ) -> Result < Option < T > , Error > {
92
110
match self . get_with_retry ( path) {
93
111
Ok ( resp) if is_status_not_found ( resp. status_code ) => Ok ( None ) ,
@@ -268,20 +286,58 @@ impl BlockingClient {
268
286
269
287
/// Broadcast a [`Transaction`] to Esplora
270
288
pub fn broadcast ( & self , transaction : & Transaction ) -> Result < ( ) , Error > {
271
- let mut request = minreq:: post ( format ! ( "{}/tx" , self . url) ) . with_body (
289
+ let request = self . post_request (
290
+ "tx" ,
272
291
serialize ( transaction)
273
292
. to_lower_hex_string ( )
274
293
. as_bytes ( )
275
294
. to_vec ( ) ,
276
- ) ;
295
+ ) ? ;
277
296
278
- if let Some ( proxy) = & self . proxy {
279
- let proxy = Proxy :: new ( proxy. as_str ( ) ) ?;
280
- request = request. with_proxy ( proxy) ;
297
+ match request. send ( ) {
298
+ Ok ( resp) if !is_status_ok ( resp. status_code ) => {
299
+ let status = u16:: try_from ( resp. status_code ) . map_err ( Error :: StatusCode ) ?;
300
+ let message = resp. as_str ( ) . unwrap_or_default ( ) . to_string ( ) ;
301
+ Err ( Error :: HttpResponse { status, message } )
302
+ }
303
+ Ok ( _resp) => Ok ( ( ) ) ,
304
+ Err ( e) => Err ( Error :: Minreq ( e) ) ,
281
305
}
306
+ }
282
307
283
- if let Some ( timeout) = & self . timeout {
284
- request = request. with_timeout ( * timeout) ;
308
+ /// Broadcast a package of [`Transaction`] to Esplora
309
+ ///
310
+ /// if `maxfeerate` is provided, any transaction whose
311
+ /// fee is higher will be rejected
312
+ ///
313
+ /// if `maxburnamount` is provided, any transaction
314
+ /// with higher provably unspendable outputs amount
315
+ /// will be rejected
316
+ pub fn broadcast_package (
317
+ & self ,
318
+ transactions : & [ Transaction ] ,
319
+ maxfeerate : Option < f64 > ,
320
+ maxburnamount : Option < f64 > ,
321
+ ) -> Result < SubmitPackageResult , Error > {
322
+ let serialized_txs = transactions
323
+ . iter ( )
324
+ . map ( |tx| serialize ( & tx) . to_lower_hex_string ( ) )
325
+ . collect :: < Vec < _ > > ( ) ;
326
+
327
+ let mut request = self . post_request (
328
+ "txs/package" ,
329
+ serde_json:: to_string ( & serialized_txs)
330
+ . unwrap ( )
331
+ . as_bytes ( )
332
+ . to_vec ( ) ,
333
+ ) ?;
334
+
335
+ if let Some ( maxfeerate) = maxfeerate {
336
+ request = request. with_param ( "maxfeerate" , maxfeerate. to_string ( ) )
337
+ }
338
+
339
+ if let Some ( maxburnamount) = maxburnamount {
340
+ request = request. with_param ( "maxburnamount" , maxburnamount. to_string ( ) )
285
341
}
286
342
287
343
match request. send ( ) {
@@ -290,7 +346,7 @@ impl BlockingClient {
290
346
let message = resp. as_str ( ) . unwrap_or_default ( ) . to_string ( ) ;
291
347
Err ( Error :: HttpResponse { status, message } )
292
348
}
293
- Ok ( _resp ) => Ok ( ( ) ) ,
349
+ Ok ( resp ) => Ok ( resp . json :: < SubmitPackageResult > ( ) . map_err ( Error :: Minreq ) ? ) ,
294
350
Err ( e) => Err ( Error :: Minreq ( e) ) ,
295
351
}
296
352
}
0 commit comments