services/explorer/cmd/commands.go
package cmd
import (
// used to embed markdown.
_ "embed"
"fmt"
markdown "github.com/MichaelMure/go-term-markdown"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/jftuga/termsize"
"github.com/phayes/freeport"
"github.com/synapsecns/sanguine/core"
"github.com/synapsecns/sanguine/core/metrics"
"github.com/synapsecns/sanguine/services/explorer/api"
indexerconfig "github.com/synapsecns/sanguine/services/explorer/config/indexer"
serverconfig "github.com/synapsecns/sanguine/services/explorer/config/server"
"github.com/synapsecns/sanguine/services/explorer/node"
"github.com/urfave/cli/v2"
)
//go:embed cmd.md
var help string
// infoCommand references the help info from the cmd.md file and presents it.
var infoCommand = &cli.Command{
Name: "info",
Description: "learn how to use explorer cli",
Action: func(c *cli.Context) error {
fmt.Println(string(markdown.Render(help, termsize.Width(), 6)))
return nil
},
}
var portFlag = &cli.UintFlag{
Name: "port",
Usage: "--port 5121",
Value: 0,
}
var clickhouseAddressFlag = &cli.StringFlag{
Name: "address",
Usage: "--address pass 'default' to use the default clickhouse address",
Value: "",
Required: false,
}
var configFlag = &cli.StringFlag{
Name: "config",
Usage: "--config /Users/synapsecns/config.yaml",
TakesFile: true,
Required: true,
}
var serverCommand = &cli.Command{
Name: "server",
Description: "starts a graphql server",
Flags: []cli.Flag{configFlag},
Action: func(c *cli.Context) error {
fmt.Println("port", c.Uint("port"))
decodeConfig, err := serverconfig.DecodeServerConfig(core.ExpandOrReturnPath(c.String(configFlag.Name)))
if err != nil {
return fmt.Errorf("could not decode config: %w", err)
}
err = api.Start(c.Context, decodeConfig, metrics.Get())
if err != nil {
return fmt.Errorf("could not start server: %w", err)
}
return nil
},
}
// nolint:dupl
var backfillCommand = &cli.Command{
Name: "backfill",
Description: "backfills up to a block and then halts",
Flags: []cli.Flag{configFlag, clickhouseAddressFlag},
Action: func(c *cli.Context) error {
decodeConfig, err := indexerconfig.DecodeConfig(core.ExpandOrReturnPath(c.String(configFlag.Name)))
if err != nil {
return fmt.Errorf("could not decode config: %w", err)
}
db, err := api.InitDB(c.Context, c.String(clickhouseAddressFlag.Name), false, metrics.Get())
if err != nil {
return fmt.Errorf("could not initialize database: %w", err)
}
clients := make(map[uint32]bind.ContractBackend)
for _, client := range decodeConfig.Chains {
backendClient, err := ethclient.DialContext(c.Context, decodeConfig.RPCURL+fmt.Sprintf("%d", client.ChainID))
if err != nil {
return fmt.Errorf("could not start client for %s", client.RPCURL)
}
clients[client.ChainID] = backendClient
}
explorerBackfiller, err := node.NewExplorerBackfiller(db, decodeConfig, clients, metrics.Get())
if err != nil {
return fmt.Errorf("could not create explorer backfiller: %w", err)
}
err = explorerBackfiller.Backfill(c.Context, false)
if err != nil {
return fmt.Errorf("could not backfill backfiller: %w", err)
}
return nil
},
}
// nolint:dupl
var livefillCommand = &cli.Command{
Name: "livefill",
Description: "livefills explorer",
Flags: []cli.Flag{configFlag, clickhouseAddressFlag},
Action: func(c *cli.Context) error {
decodeConfig, err := indexerconfig.DecodeConfig(core.ExpandOrReturnPath(c.String(configFlag.Name)))
if err != nil {
return fmt.Errorf("could not decode config: %w", err)
}
db, err := api.InitDB(c.Context, c.String(clickhouseAddressFlag.Name), false, metrics.Get())
if err != nil {
return fmt.Errorf("could not initialize database: %w", err)
}
clients := make(map[uint32]bind.ContractBackend)
for _, client := range decodeConfig.Chains {
backendClient, err := ethclient.DialContext(c.Context, decodeConfig.RPCURL+fmt.Sprintf("%d", client.ChainID))
if err != nil {
return fmt.Errorf("could not start client for %s", client.RPCURL)
}
clients[client.ChainID] = backendClient
}
explorerBackfiller, err := node.NewExplorerBackfiller(db, decodeConfig, clients, metrics.Get())
if err != nil {
return fmt.Errorf("could not create explorer backfiller: %w", err)
}
err = explorerBackfiller.Backfill(c.Context, true)
if err != nil {
return fmt.Errorf("could not backfill backfiller: %w", err)
}
return nil
},
}
func init() {
portFlag.Value = uint(freeport.GetPort())
}