github.com/mavryk-network/mvgo@v1.19.9/cmd/tzcompose/main.go (about)

     1  // Copyright (c) 2023 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc, abdul@blockwatch.cc
     3  
     4  package main
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"flag"
    10  	"fmt"
    11  	"os"
    12  	"os/signal"
    13  	"strings"
    14  	"time"
    15  
    16  	"github.com/mavryk-network/mvgo/internal/compose"
    17  	"github.com/mavryk-network/mvgo/mavryk"
    18  
    19  	_ "github.com/mavryk-network/mvgo/internal/compose/alpha"
    20  	_ "github.com/mavryk-network/mvgo/internal/compose/alpha/task"
    21  )
    22  
    23  var (
    24  	flags      = flag.NewFlagSet(appName, flag.ContinueOnError)
    25  	runflags   = flag.NewFlagSet("run", flag.ContinueOnError)
    26  	cloneflags = flag.NewFlagSet("clone", flag.ContinueOnError)
    27  	errExit    = errors.New("exit")
    28  	errNoCmd   = errors.New("unsupported command")
    29  	verbose    bool
    30  	vtrace     bool
    31  	vdebug     bool
    32  	cmd        string = "[cmd]"
    33  
    34  	// run config
    35  	fpath  string
    36  	resume bool
    37  	rpcUrl string
    38  
    39  	// clone config
    40  	name                   string
    41  	mode                   compose.CloneMode
    42  	addr                   mavryk.Address
    43  	numOpsAfterOrigination uint
    44  	version                string
    45  	indexUrl               string
    46  	outputPath             string
    47  )
    48  
    49  func init() {
    50  	flags.Usage = func() {}
    51  	flags.BoolVar(&verbose, "v", true, "be verbose")
    52  	flags.BoolVar(&vdebug, "vv", false, "debug mode")
    53  	flags.BoolVar(&vtrace, "vvv", false, "trace mode")
    54  
    55  	runflags.Usage = func() {}
    56  	runflags.StringVar(&fpath, "f", "tzcompose.yaml", "configuration `file` or path")
    57  	runflags.StringVar(&fpath, "file", "tzcompose.yaml", "configuration `file` or path")
    58  	runflags.BoolVar(&resume, "resume", false, "continue pipeline execution")
    59  	runflags.StringVar(&rpcUrl, "rpc", "https://rpc.tzpro.io", "Tezos node RPC url")
    60  
    61  	cloneflags.Usage = func() {}
    62  	cloneflags.StringVar(&indexUrl, "index", "https://api.tzpro.io", "Tezos indexer url")
    63  	cloneflags.StringVar(&rpcUrl, "rpc", "https://rpc.tzpro.io", "Tezos node RPC url")
    64  	cloneflags.StringVar(&version, "version", "alpha", "compose engine version")
    65  	cloneflags.Var(&addr, "contract", "address of the contract to clone")
    66  	cloneflags.Var(&mode, "mode", "output mode for cloned micheline data (file, json, bin, url)")
    67  	cloneflags.StringVar(&name, "name", "contract", "project name")
    68  	cloneflags.StringVar(&outputPath, "out", "tzcompose.yaml", "output path for generated files")
    69  	cloneflags.UintVar(&numOpsAfterOrigination, "n", 0, "number of operations after origination")
    70  }
    71  
    72  func main() {
    73  	if err := parseFlags(); err != nil {
    74  		if err != errExit {
    75  			fmt.Println("Error:", err)
    76  		}
    77  		return
    78  	}
    79  	initLogging()
    80  
    81  	if err := run(); err != nil {
    82  		fmt.Println("Error:", err)
    83  	}
    84  }
    85  
    86  func run() error {
    87  	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    88  	defer stop()
    89  
    90  	ectx := compose.NewContext(ctx)
    91  	ectx.WithLogger(taskLog).
    92  		WithUrl(rpcUrl).
    93  		WithApiKey(os.Getenv("TZCOMPOSE_API_KEY")).
    94  		WithBase(os.Getenv("TZCOMPOSE_BASE_KEY")).
    95  		WithResume(resume)
    96  
    97  	var err error
    98  	switch cmd {
    99  	case "version":
   100  		printVersion()
   101  	case "validate":
   102  		err = compose.Run(ectx, fpath, compose.RunModeValidate)
   103  	case "simulate":
   104  		err = compose.Run(ectx, fpath, compose.RunModeSimulate)
   105  	case "run":
   106  		err = compose.Run(ectx, fpath, compose.RunModeExecute)
   107  	case "clone":
   108  		err = compose.Clone(ectx, version, compose.CloneConfig{
   109  			Name:     name,
   110  			Contract: addr,
   111  			IndexUrl: indexUrl,
   112  			NumOps:   numOpsAfterOrigination,
   113  			Path:     outputPath,
   114  			Mode:     mode,
   115  		})
   116  	default:
   117  		err = errNoCmd
   118  	}
   119  	return err
   120  }
   121  
   122  func parseFlags() error {
   123  	if len(os.Args) < 2 {
   124  		printHelp()
   125  		return errExit
   126  	}
   127  
   128  	n := 1
   129  	if !strings.HasPrefix(os.Args[n], "-") {
   130  		cmd = os.Args[n]
   131  		n++
   132  	}
   133  
   134  	switch cmd {
   135  	case "validate", "simulate", "run", "clone", "version", "[cmd]":
   136  		// ok
   137  	default:
   138  		return errNoCmd
   139  	}
   140  
   141  	// parse global flags
   142  	err := flags.Parse(filterFlags(flags, os.Args[n:]))
   143  	if err != nil {
   144  		if err == flag.ErrHelp {
   145  			printHelp()
   146  			return errExit
   147  		}
   148  	}
   149  
   150  	// parse command flags
   151  	switch cmd {
   152  	case "validate", "simulate", "run":
   153  		err = runflags.Parse(filterFlags(runflags, os.Args[2:]))
   154  	case "clone":
   155  		err = cloneflags.Parse(filterFlags(cloneflags, os.Args[2:]))
   156  	}
   157  	if err != nil {
   158  		if err == flag.ErrHelp {
   159  			printHelp()
   160  			return errExit
   161  		}
   162  		return err
   163  	}
   164  	return nil
   165  }
   166  
   167  func filterFlags(set *flag.FlagSet, args []string) []string {
   168  	res := make([]string, 0)
   169  	var maybeCopyNext bool
   170  	for _, v := range args {
   171  		if strings.HasPrefix(v, "-") {
   172  			f := set.Lookup(v[1:])
   173  			if f == nil && v != "-h" {
   174  				maybeCopyNext = false
   175  				continue
   176  			}
   177  			maybeCopyNext = true
   178  			res = append(res, v)
   179  		} else if maybeCopyNext {
   180  			maybeCopyNext = false
   181  			res = append(res, v)
   182  		}
   183  	}
   184  	return res
   185  }
   186  
   187  func printHelp() {
   188  	fmt.Printf("(c) Copyright (c) %d Blockwatch Data Inc.\n", time.Now().Year())
   189  	fmt.Printf("Usage:  %s %s [flags]\n", appName, cmd)
   190  	switch cmd {
   191  	case "validate", "simulate", "run":
   192  		fmt.Printf("\nEnv\n")
   193  		fmt.Println("  TZCOMPOSE_BASE_KEY  private key for base account")
   194  		fmt.Println("  TZCOMPOSE_API_KEY   API key for RPC and index calls (optional)")
   195  		fmt.Println("\nFlags")
   196  		runflags.PrintDefaults()
   197  		fmt.Println("  -h	print help and exit")
   198  		flags.PrintDefaults()
   199  	case "clone":
   200  		fmt.Printf("\nEnv\n")
   201  		fmt.Println("  TZCOMPOSE_BASE_KEY  private key for base account")
   202  		fmt.Println("  TZCOMPOSE_API_KEY   API key for RPC and index calls (optional)")
   203  		fmt.Println("\nFlags")
   204  		cloneflags.PrintDefaults()
   205  		fmt.Println("  -h	print help and exit")
   206  		flags.PrintDefaults()
   207  	default:
   208  		fmt.Printf("\nCommands\n")
   209  		fmt.Println("  clone     Clone a contract and its transactions")
   210  		fmt.Println("  validate  Check compose file syntax and parameters")
   211  		fmt.Println("  simulate  Simulate compose file execution")
   212  		fmt.Println("  run       Execute compose file(s)")
   213  		fmt.Println("  version   Print version and exit")
   214  		fmt.Println("\nFlags")
   215  		fmt.Println("  -h	print help and exit")
   216  		flags.PrintDefaults()
   217  	}
   218  }