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 }