@@ -3,17 +3,20 @@ use crate::{
3
3
signer:: LocalOrAws ,
4
4
tasks:: block:: InProgressBlock ,
5
5
} ;
6
- use alloy:: consensus:: { constants:: GWEI_TO_WEI , SimpleCoder } ;
7
- use alloy:: eips:: BlockNumberOrTag ;
8
- use alloy:: network:: { TransactionBuilder , TransactionBuilder4844 } ;
9
- use alloy:: providers:: { Provider as _, WalletProvider } ;
10
- use alloy:: rpc:: types:: eth:: TransactionRequest ;
11
- use alloy:: signers:: Signer ;
12
- use alloy:: sol_types:: SolCall ;
13
- use alloy:: transports:: TransportError ;
6
+ use alloy:: {
7
+ consensus:: { constants:: GWEI_TO_WEI , SimpleCoder } ,
8
+ eips:: BlockNumberOrTag ,
9
+ network:: { TransactionBuilder , TransactionBuilder4844 } ,
10
+ providers:: SendableTx ,
11
+ providers:: { Provider as _, WalletProvider } ,
12
+ rpc:: types:: eth:: TransactionRequest ,
13
+ signers:: Signer ,
14
+ sol_types:: SolCall ,
15
+ transports:: TransportError ,
16
+ } ;
14
17
use alloy_primitives:: { FixedBytes , U256 } ;
15
18
use alloy_sol_types:: SolError ;
16
- use eyre:: eyre;
19
+ use eyre:: { bail , eyre} ;
17
20
use oauth2:: {
18
21
basic:: BasicClient , basic:: BasicTokenType , reqwest:: http_client, AuthUrl , ClientId ,
19
22
ClientSecret , EmptyExtraTokenFields , StandardTokenResponse , TokenResponse , TokenUrl ,
@@ -25,6 +28,20 @@ use zenith_types::{
25
28
Zenith :: { self , IncorrectHostBlock } ,
26
29
} ;
27
30
31
+ macro_rules! spawn_provider_send {
32
+ ( $provider: expr, $tx: expr) => {
33
+ {
34
+ let p = $provider. clone( ) ;
35
+ let t = $tx. clone( ) ;
36
+ tokio:: spawn( async move {
37
+ p. send_tx_envelope( t) . await . inspect_err( |e| {
38
+ tracing:: warn!( %e, "error in transaction broadcast" )
39
+ } )
40
+ } )
41
+ }
42
+ } ;
43
+ }
44
+
28
45
/// OAuth Audience Claim Name, required param by IdP for client credential grant
29
46
const OAUTH_AUDIENCE_CLAIM : & str = "audience" ;
30
47
@@ -186,21 +203,41 @@ impl SubmitTask {
186
203
return Ok ( ControlFlow :: Skip ) ;
187
204
}
188
205
206
+ self . send_transaction ( resp, tx) . await
207
+ }
208
+
209
+ async fn send_transaction (
210
+ & self ,
211
+ resp : & SignResponse ,
212
+ tx : TransactionRequest ,
213
+ ) -> Result < ControlFlow , eyre:: Error > {
189
214
tracing:: debug!(
190
215
host_block_number = %resp. req. host_block_number,
191
216
gas_limit = %resp. req. gas_limit,
192
217
"sending transaction to network"
193
218
) ;
194
219
195
- let _ = match self . provider . send_transaction ( tx) . await {
196
- Ok ( result) => result,
197
- Err ( e) => {
198
- error ! ( error = %e, "error sending transaction" ) ;
199
- return Ok ( ControlFlow :: Skip ) ;
200
- }
220
+ let SendableTx :: Envelope ( tx) = self . provider . fill ( tx) . await ? else {
221
+ bail ! ( "failed to fill transaction" )
201
222
} ;
202
223
224
+ // Send the tx via the primary provider
225
+ let fut = spawn_provider_send ! ( & self . provider, & tx) ;
226
+
227
+ // Spawn send_tx futures for all additional broadcast providers
228
+ for provider in self . config . connect_additional_broadcast ( ) . await ? {
229
+ spawn_provider_send ! ( & provider, & tx) ;
230
+ }
231
+
232
+ // question mark unwraps join error, which would be an internal panic
233
+ // then if let checks for rpc error
234
+ if let Err ( e) = fut. await ? {
235
+ tracing:: error!( error = %e, "Primary tx broadcast failed. Skipping transaction." ) ;
236
+ return Ok ( ControlFlow :: Skip ) ;
237
+ }
238
+
203
239
tracing:: info!(
240
+ tx_hash = %tx. tx_hash( ) ,
204
241
ru_chain_id = %resp. req. ru_chain_id,
205
242
gas_limit = %resp. req. gas_limit,
206
243
"dispatched to network"
0 commit comments