11use crate :: client:: { ProgramClient , ProgramClientError , SendTransaction } ;
2+ use solana_program_test:: tokio:: time;
23use solana_sdk:: {
34 account:: Account as BaseAccount ,
5+ hash:: Hash ,
46 instruction:: Instruction ,
57 program_error:: ProgramError ,
68 pubkey:: Pubkey ,
@@ -18,7 +20,11 @@ use spl_token_2022::{
1820 instruction,
1921 state:: { Account , AccountState , Mint } ,
2022} ;
21- use std:: { fmt, sync:: Arc } ;
23+ use std:: {
24+ fmt, io,
25+ sync:: Arc ,
26+ time:: { Duration , Instant } ,
27+ } ;
2228use thiserror:: Error ;
2329
2430#[ derive( Error , Debug ) ]
@@ -165,21 +171,54 @@ where
165171 }
166172 }
167173
174+ pub async fn get_new_latest_blockhash ( & self ) -> TokenResult < Hash > {
175+ let blockhash = self
176+ . client
177+ . get_latest_blockhash ( )
178+ . await
179+ . map_err ( TokenError :: Client ) ?;
180+ let start = Instant :: now ( ) ;
181+ let mut num_retries = 0 ;
182+ while start. elapsed ( ) . as_secs ( ) < 5 {
183+ let new_blockhash = self
184+ . client
185+ . get_latest_blockhash ( )
186+ . await
187+ . map_err ( TokenError :: Client ) ?;
188+ if new_blockhash != blockhash {
189+ return Ok ( new_blockhash) ;
190+ }
191+
192+ time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
193+ num_retries += 1 ;
194+ }
195+
196+ Err ( TokenError :: Client ( Box :: new ( io:: Error :: new (
197+ io:: ErrorKind :: Other ,
198+ format ! (
199+ "Unable to get new blockhash after {}ms (retried {} times), stuck at {}" ,
200+ start. elapsed( ) . as_millis( ) ,
201+ num_retries,
202+ blockhash
203+ ) ,
204+ ) ) ) )
205+ }
206+
168207 pub async fn process_ixs < S2 : Signers > (
169208 & self ,
170209 instructions : & [ Instruction ] ,
171210 signing_keypairs : & S2 ,
172211 ) -> TokenResult < T :: Output > {
173- let recent_blockhash = self
212+ let latest_blockhash = self
174213 . client
175214 . get_latest_blockhash ( )
176215 . await
177216 . map_err ( TokenError :: Client ) ?;
178217
179218 let mut tx = Transaction :: new_with_payer ( instructions, Some ( & self . payer . pubkey ( ) ) ) ;
180- tx. try_partial_sign ( & [ & self . payer ] , recent_blockhash )
219+ tx. try_partial_sign ( & [ & self . payer ] , latest_blockhash )
181220 . map_err ( |error| TokenError :: Client ( error. into ( ) ) ) ?;
182- tx. try_sign ( signing_keypairs, recent_blockhash )
221+ tx. try_sign ( signing_keypairs, latest_blockhash )
183222 . map_err ( |error| TokenError :: Client ( error. into ( ) ) ) ?;
184223
185224 self . client
0 commit comments