github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/cli/chain_watch.go (about)

     1  package cli
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"strings"
     9  	"syscall"
    10  
    11  	"github.com/ethereum/go-ethereum/core"
    12  	"github.com/ethereum/go-ethereum/internal/cli/flagset"
    13  	"github.com/ethereum/go-ethereum/internal/cli/server/proto"
    14  )
    15  
    16  // ChainWatchCommand is the command to group the peers commands
    17  type ChainWatchCommand struct {
    18  	*Meta2
    19  }
    20  
    21  // MarkDown implements cli.MarkDown interface
    22  func (c *ChainWatchCommand) MarkDown() string {
    23  	items := []string{
    24  		"# Chain watch",
    25  		"The ```chain watch``` command is used to view the chainHead, reorg and fork events in real-time.",
    26  	}
    27  
    28  	return strings.Join(items, "\n\n")
    29  }
    30  
    31  // Help implements the cli.Command interface
    32  func (c *ChainWatchCommand) Help() string {
    33  	return `Usage: bor chain watch
    34  
    35    This command is used to view the chainHead, reorg and fork events in real-time`
    36  }
    37  
    38  func (c *ChainWatchCommand) Flags() *flagset.Flagset {
    39  	flags := c.NewFlagSet("chain watch")
    40  
    41  	return flags
    42  }
    43  
    44  // Synopsis implements the cli.Command interface
    45  func (c *ChainWatchCommand) Synopsis() string {
    46  	return "Watch the chainHead, reorg and fork events in real-time"
    47  }
    48  
    49  // Run implements the cli.Command interface
    50  func (c *ChainWatchCommand) Run(args []string) int {
    51  	flags := c.Flags()
    52  	if err := flags.Parse(args); err != nil {
    53  		c.UI.Error(err.Error())
    54  		return 1
    55  	}
    56  
    57  	borClt, err := c.BorConn()
    58  	if err != nil {
    59  		c.UI.Error(err.Error())
    60  		return 1
    61  	}
    62  
    63  	sub, err := borClt.ChainWatch(context.Background(), &proto.ChainWatchRequest{})
    64  	if err != nil {
    65  		c.UI.Error(err.Error())
    66  		return 1
    67  	}
    68  
    69  	signalCh := make(chan os.Signal, 1)
    70  	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
    71  
    72  	go func() {
    73  		<-signalCh
    74  
    75  		if err := sub.CloseSend(); err != nil {
    76  			c.UI.Error(err.Error())
    77  		}
    78  	}()
    79  
    80  	for {
    81  		msg, err := sub.Recv()
    82  		if err != nil {
    83  			// if err == EOF if finished on the other side
    84  			c.UI.Output(err.Error())
    85  			break
    86  		}
    87  
    88  		c.UI.Output(formatHeadEvent(msg))
    89  	}
    90  
    91  	return 0
    92  }
    93  
    94  func formatHeadEvent(msg *proto.ChainWatchResponse) string {
    95  	var out string
    96  	if msg.Type == core.Chain2HeadCanonicalEvent {
    97  		out = fmt.Sprintf("Block Added : %v", msg.Newchain)
    98  	} else if msg.Type == core.Chain2HeadForkEvent {
    99  		out = fmt.Sprintf("New Fork Block : %v", msg.Newchain)
   100  	} else if msg.Type == core.Chain2HeadReorgEvent {
   101  		out = fmt.Sprintf("Reorg Detected \nAdded : %v \nRemoved : %v", msg.Newchain, msg.Oldchain)
   102  	}
   103  
   104  	return out
   105  }