diff --git a/README.md b/README.md index cfc300c..020a07c 100644 --- a/README.md +++ b/README.md @@ -3,27 +3,37 @@ `cbctl` is a CLI tool for interacting with the Chainbound backend. ## Installation + With Go: + ```bash go install github.com/chainbound/cbctl@latest ``` ## Usage + First, initialize `cbctl` with your API key. This will write a config file to `~/.config/cbctl/config.toml`: + ```bash cbctl init --key ``` ### Fiber Commands + The `fiber` subcommand let's you interact with the Fiber backend. -* `cbctl fiber quota` +- `cbctl fiber quota` Gets your quota for the current billing period. -* `cbctl fiber trace tx --hash ` + +- `cbctl fiber trace tx --hash ` Gets the trace for a transaction. Run `cbctl fiber trace tx --help` for more info. -* `cbctl fiber trace block --hash ` or `cbctl fiber trace block --number ` +- `cbctl fiber trace block --hash ` or `cbctl fiber trace block --number ` Gets a block trace. Run `cbctl fiber trace block --help` for more info. + +- `cbctl fiber trace blob --commitment ` + +Gets a blob trace. Run `cbctl fiber trace blob --help` for more info. diff --git a/api/fiber.go b/api/fiber.go index 83def71..2e06c57 100644 --- a/api/fiber.go +++ b/api/fiber.go @@ -157,3 +157,43 @@ func (f *FiberAPI) TraceBlock(hashOrNumber, observationType string) ([]*TraceEnt return response.Message, nil } + +func (f *FiberAPI) TraceBlob(commitment string, observationType string) ([]*TraceEntry, error) { + req, err := http.NewRequest("GET", f.url+"/trace/blob/"+commitment, nil) + if err != nil { + return nil, err + } + + if observationType == "" { + observationType = "all" + } + + q := req.URL.Query() + q.Add("observation_type", observationType) + req.URL.RawQuery = q.Encode() + + f.prepareRequest(req) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + response := new(Response[[]*TraceEntry]) + if err := json.Unmarshal(body, response); err != nil { + return nil, err + } + + if response.Status != "success" { + return nil, fmt.Errorf("Error getting quota: %s", response.Error) + } + + return response.Message, nil +} diff --git a/cli.go b/cli.go index 279c2bf..8ec9ac5 100644 --- a/cli.go +++ b/cli.go @@ -182,6 +182,54 @@ func NewApp() *cli.App { printMessageTrace(traces, showSource) + return nil + }, + }, + { + Name: "blob", + Usage: "Trace a blob sidecar (consensus layer)", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "commitment", + Aliases: []string{"C"}, + Usage: "The blob KZG commitment to trace", + Required: true, + }, + &cli.StringFlag{ + Name: "type", + Aliases: []string{"t"}, + Usage: "The observation type to trace (p2p | fiber | all)", + Value: "all", + }, + &cli.BoolFlag{ + Name: "show-source", + Aliases: []string{"s"}, + Usage: "Whether or not to show the source of the transaction", + Value: false, + }, + }, + Action: func(c *cli.Context) error { + cfg, err := ReadConfig() + if err != nil { + return fmt.Errorf("Error reading config, did you run cbctl init?: %w", err) + } + + commitment := c.String("commitment") + if commitment == "" { + return fmt.Errorf("Must specify a blob commitment") + } + + observationType := c.String("type") + showSource := c.Bool("show-source") + + api := api.NewFiberAPI(cfg.Url, cfg.ApiKey) + traces, err := api.TraceBlob(commitment, observationType) + if err != nil { + return fmt.Errorf("Error getting quota: %w", err) + } + + printMessageTrace(traces, showSource) + return nil }, }, diff --git a/fmt.go b/fmt.go index a53d72f..e2b8317 100644 --- a/fmt.go +++ b/fmt.go @@ -11,6 +11,11 @@ import ( ) func printMessageTrace(trace []*api.TraceEntry, showSource bool) { + if len(trace) == 0 { + fmt.Println("No trace entries found") + return + } + t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.SetStyle(table.StyleLight)