package utils import ( "context" "fmt" "math/big" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/rpc" ) type ethClient interface { BlockNumber(ctx context.Context) (uint64, error) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) } // GetLatestConfirmedBlockNumber get confirmed block number by rpc.BlockNumber type. func GetLatestConfirmedBlockNumber(ctx context.Context, client ethClient, confirm rpc.BlockNumber) (uint64, error) { switch true { case confirm == rpc.SafeBlockNumber || confirm == rpc.FinalizedBlockNumber: var tag *big.Int if confirm == rpc.FinalizedBlockNumber { tag = big.NewInt(int64(rpc.FinalizedBlockNumber)) } else { tag = big.NewInt(int64(rpc.SafeBlockNumber)) } header, err := client.HeaderByNumber(ctx, tag) if err != nil { return 0, err } if !header.Number.IsInt64() { return 0, fmt.Errorf("received invalid block confirm: %v", header.Number) } return header.Number.Uint64(), nil case confirm == rpc.LatestBlockNumber: number, err := client.BlockNumber(ctx) if err != nil { return 0, err } return number, nil case confirm.Int64() >= 0: // If it's positive integer, consider it as a certain confirm value. number, err := client.BlockNumber(ctx) if err != nil { return 0, err } cfmNum := uint64(confirm.Int64()) if number >= cfmNum { return number - cfmNum, nil } return 0, nil default: return 0, fmt.Errorf("unknown confirmation type: %v", confirm) } }