@@ -39,6 +39,8 @@ type Tracker[H chains.Head[BLOCK_HASH], BLOCK_HASH chains.Hashable] interface {
3939 // Backfill given a head will fill in any missing heads up to latestFinalized
4040 Backfill (ctx context.Context , headWithChain H , prevHeadWithChain H ) (err error )
4141 LatestChain () H
42+ // LatestSafeBlock returns the latest block that is considered safe to use.
43+ LatestSafeBlock (ctx context.Context ) (safe H , err error )
4244 // LatestAndFinalizedBlock - returns latest and latest finalized blocks.
4345 // NOTE: Returns latest finalized block as is, ignoring the FinalityTagBypass feature flag.
4446 LatestAndFinalizedBlock (ctx context.Context ) (latest , finalized H , err error )
@@ -47,6 +49,7 @@ type Tracker[H chains.Head[BLOCK_HASH], BLOCK_HASH chains.Hashable] interface {
4749type ChainConfig interface {
4850 BlockEmissionIdleWarningThreshold () time.Duration
4951 FinalityDepth () uint32
52+ SafeDepth () uint32
5053 FinalityTagEnabled () bool
5154 FinalizedBlockOffset () uint32
5255}
@@ -396,6 +399,42 @@ func (t *tracker[HTH, S, ID, BHASH]) backfillLoop(ctx context.Context) {
396399 }
397400}
398401
402+ func (t * tracker [HTH , S , ID , BHASH ]) LatestSafeBlock (ctx context.Context ) (safe HTH , err error ) {
403+ if t .config .FinalityTagEnabled () {
404+ latestSafe , err2 := t .client .LatestSafeBlock (ctx )
405+ if err2 != nil {
406+ return latestSafe , fmt .Errorf ("failed to get latest finalized block: %w" , err2 )
407+ }
408+
409+ if ! latestSafe .IsValid () {
410+ return latestSafe , fmt .Errorf ("failed to get valid latest finalized block" )
411+ }
412+ return latestSafe , nil
413+ }
414+ latest , err := t .client .HeadByNumber (ctx , nil )
415+ if err != nil {
416+ err = fmt .Errorf ("failed to get latest block: %w" , err )
417+ return
418+ }
419+
420+ if ! latest .IsValid () {
421+ err = fmt .Errorf ("expected latest block to be valid" )
422+ return
423+ }
424+ if t .instantFinality () {
425+ return latest , nil
426+ }
427+ safeDepth := int64 (t .config .SafeDepth ())
428+ if safeDepth <= 0 {
429+ safeDepth = int64 (t .config .FinalityDepth ())
430+ }
431+ safeBlockNumber := latest .BlockNumber () - safeDepth
432+ if safeBlockNumber <= 0 {
433+ safeBlockNumber = 0
434+ }
435+ return t .getHeadAtHeight (ctx , latest .BlockHash (), safeBlockNumber )
436+ }
437+
399438// LatestAndFinalizedBlock - returns latest and latest finalized blocks.
400439// NOTE: Returns latest finalized block as is, ignoring the FinalityTagBypass feature flag.
401440// TODO: BCI-3321 use cached values instead of making RPC requests
0 commit comments