github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/cli/smartcontract/generate.go (about) 1 package smartcontract 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/nspcc-dev/neo-go/cli/cmdargs" 9 "github.com/nspcc-dev/neo-go/pkg/smartcontract/binding" 10 "github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding" 11 "github.com/nspcc-dev/neo-go/pkg/util" 12 "github.com/urfave/cli" 13 "gopkg.in/yaml.v3" 14 ) 15 16 var generatorFlags = []cli.Flag{ 17 cli.StringFlag{ 18 Name: "config, c", 19 Usage: "Configuration file to use", 20 }, 21 cli.StringFlag{ 22 Name: "manifest, m", 23 Required: true, 24 Usage: "Read contract manifest (*.manifest.json) file", 25 }, 26 cli.StringFlag{ 27 Name: "out, o", 28 Required: true, 29 Usage: "Output of the compiled wrapper", 30 }, 31 cli.StringFlag{ 32 Name: "hash", 33 Usage: "Smart-contract hash. If not passed, the wrapper will be designed for dynamic hash usage", 34 }, 35 } 36 37 var generateWrapperCmd = cli.Command{ 38 Name: "generate-wrapper", 39 Usage: "generate wrapper to use in other contracts", 40 UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]", 41 Description: `Generates a Go wrapper to use it in other smart contracts. If the 42 --hash flag is provided, CALLT instruction is used for the target contract 43 invocation as an optimization of the wrapper contract code. If omitted, the 44 generated wrapper will be designed for dynamic hash usage, allowing 45 the hash to be specified at runtime. 46 `, 47 Action: contractGenerateWrapper, 48 Flags: generatorFlags, 49 } 50 51 var generateRPCWrapperCmd = cli.Command{ 52 Name: "generate-rpcwrapper", 53 Usage: "generate RPC wrapper to use for data reads", 54 UsageText: "neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]", 55 Action: contractGenerateRPCWrapper, 56 Flags: generatorFlags, 57 } 58 59 func contractGenerateWrapper(ctx *cli.Context) error { 60 return contractGenerateSomething(ctx, binding.Generate) 61 } 62 63 func contractGenerateRPCWrapper(ctx *cli.Context) error { 64 return contractGenerateSomething(ctx, rpcbinding.Generate) 65 } 66 67 // contractGenerateSomething reads generator parameters and calls the given callback. 68 func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error) error { 69 if err := cmdargs.EnsureNone(ctx); err != nil { 70 return err 71 } 72 var ( 73 h util.Uint160 74 err error 75 ) 76 if hStr := ctx.String("hash"); len(hStr) != 0 { 77 h, err = util.Uint160DecodeStringLE(strings.TrimPrefix(hStr, "0x")) 78 if err != nil { 79 return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1) 80 } 81 } 82 m, _, err := readManifest(ctx.String("manifest"), h) 83 if err != nil { 84 return cli.NewExitError(fmt.Errorf("can't read contract manifest: %w", err), 1) 85 } 86 87 cfg := binding.NewConfig() 88 if cfgPath := ctx.String("config"); cfgPath != "" { 89 bs, err := os.ReadFile(cfgPath) 90 if err != nil { 91 return cli.NewExitError(fmt.Errorf("can't read config file: %w", err), 1) 92 } 93 err = yaml.Unmarshal(bs, &cfg) 94 if err != nil { 95 return cli.NewExitError(fmt.Errorf("can't parse config file: %w", err), 1) 96 } 97 } 98 cfg.Manifest = m 99 cfg.Hash = h 100 101 f, err := os.Create(ctx.String("out")) 102 if err != nil { 103 return cli.NewExitError(fmt.Errorf("can't create output file: %w", err), 1) 104 } 105 defer f.Close() 106 107 cfg.Output = f 108 109 err = cb(cfg) 110 if err != nil { 111 return cli.NewExitError(fmt.Errorf("error during generation: %w", err), 1) 112 } 113 return nil 114 }