@@ -31,8 +31,8 @@ use bitcoin::{
3131
3232use  crate :: api:: AddressStats ; 
3333use  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 , 
3636} ; 
3737
3838#[ derive( Debug ,  Clone ) ]  
@@ -88,6 +88,24 @@ impl BlockingClient {
8888        Ok ( request) 
8989    } 
9090
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+ 
91109    fn  get_opt_response < T :  Decodable > ( & self ,  path :  & str )  -> Result < Option < T > ,  Error >  { 
92110        match  self . get_with_retry ( path)  { 
93111            Ok ( resp)  if  is_status_not_found ( resp. status_code )  => Ok ( None ) , 
@@ -268,20 +286,58 @@ impl BlockingClient {
268286
269287    /// Broadcast a [`Transaction`] to Esplora 
270288pub  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" , 
272291            serialize ( transaction) 
273292                . to_lower_hex_string ( ) 
274293                . as_bytes ( ) 
275294                . to_vec ( ) , 
276-         ) ; 
295+         ) ? ; 
277296
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) ) , 
281305        } 
306+     } 
282307
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  submit_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 ( ) ) 
285341        } 
286342
287343        match  request. send ( )  { 
@@ -290,7 +346,7 @@ impl BlockingClient {
290346                let  message = resp. as_str ( ) . unwrap_or_default ( ) . to_string ( ) ; 
291347                Err ( Error :: HttpResponse  {  status,  message } ) 
292348            } 
293-             Ok ( _resp )  => Ok ( ( ) ) , 
349+             Ok ( resp )  => Ok ( resp . json :: < SubmitPackageResult > ( ) . map_err ( Error :: Minreq ) ? ) , 
294350            Err ( e)  => Err ( Error :: Minreq ( e) ) , 
295351        } 
296352    } 
0 commit comments