From 54b578c2e9ca81a0c68a768997105c76d7782caa Mon Sep 17 00:00:00 2001 From: colindickson Date: Mon, 4 Nov 2024 08:07:32 -0500 Subject: [PATCH] cmd: added tool to find next valid block using rpc --- cmd/firesol/main.go | 4 +-- cmd/firesol/rpc/check.go | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 cmd/firesol/rpc/check.go diff --git a/cmd/firesol/main.go b/cmd/firesol/main.go index e4a6b872..39a2bd4a 100644 --- a/cmd/firesol/main.go +++ b/cmd/firesol/main.go @@ -27,9 +27,8 @@ func init() { } func main() { - if err := rootCmd.Execute(); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Whoops. There was an error while executing your CLI '%s'", err) + _, _ = fmt.Fprintf(os.Stderr, "Oops! There was an error while executing your command '%s'", err) os.Exit(1) } } @@ -42,5 +41,6 @@ func newFetchCmd(logger *zap.Logger, tracer logging.Tracer) *cobra.Command { } time.Now().UnixMilli() cmd.AddCommand(rpc.NewFetchCmd(logger, tracer)) + cmd.AddCommand(rpc.NewNextBlockCmd(logger, tracer)) return cmd } diff --git a/cmd/firesol/rpc/check.go b/cmd/firesol/rpc/check.go new file mode 100644 index 00000000..ccc0b31b --- /dev/null +++ b/cmd/firesol/rpc/check.go @@ -0,0 +1,77 @@ +// cmd/firesol/rpc/check_block.go +package rpc + +import ( + "context" + "fmt" + "strconv" + "time" + + "github.com/streamingfast/firehose-solana/block/fetcher" + + firecoreRPC "github.com/streamingfast/firehose-core/rpc" + + "github.com/gagliardetto/solana-go/rpc" + "github.com/spf13/cobra" + "github.com/streamingfast/cli/sflags" + firecore "github.com/streamingfast/firehose-core" + "github.com/streamingfast/logging" + "go.uber.org/zap" +) + +func NewNextBlockCmd(logger *zap.Logger, tracer logging.Tracer) *cobra.Command { + cmd := &cobra.Command{ + Use: "next ", + Short: "Check if a block exists and return the next available block", + Args: cobra.ExactArgs(1), + RunE: nextBlockRunE(logger, tracer), + } + + cmd.Flags().StringArray("endpoints", []string{}, "List of endpoints to use to fetch different method calls") + + return cmd +} + +func nextBlockRunE(logger *zap.Logger, _ logging.Tracer) firecore.CommandExecutor { + return func(cmd *cobra.Command, args []string) (err error) { + ctx := cmd.Context() + + startBlock, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return fmt.Errorf("unable to parse block number %d: %w", startBlock, err) + } + + rpcEndpoints := sflags.MustGetStringArray(cmd, "endpoints") + rpcClients := firecoreRPC.NewClients[*rpc.Client]() + for _, rpcEndpoint := range rpcEndpoints { + client := rpc.New(rpcEndpoint) + rpcClients.Add(client) + } + + rpcFetcher := fetcher.NewRPC(rpcClients, 1*time.Second, 1*time.Second, logger) + + var blockExists bool + for !blockExists { + select { + case <-ctx.Done(): + break + default: + + } + + blockExists = checkBlockExists(ctx, rpcFetcher, startBlock) + if blockExists { + break + } + startBlock++ + } + + _, _ = fmt.Fprintf(cmd.OutOrStdout(), fmt.Sprintf("%d", startBlock)) + return nil + } +} + +func checkBlockExists(ctx context.Context, rpcFetcher *fetcher.RPCFetcher, blockNumber uint64) bool { + _, skip, err := rpcFetcher.Fetch(ctx, blockNumber) + return !skip && err == nil +}