2021-10-25 11:48:21 +00:00
|
|
|
package smartcontract
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2022-02-25 07:27:51 +00:00
|
|
|
"strings"
|
2021-10-25 11:48:21 +00:00
|
|
|
|
2022-08-05 10:32:37 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
2021-10-25 11:48:21 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/binding"
|
2022-10-26 20:27:24 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/rpcbinding"
|
2021-10-25 11:48:21 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
2024-07-09 18:24:39 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
2021-09-25 10:09:55 +00:00
|
|
|
"gopkg.in/yaml.v3"
|
2021-10-25 11:48:21 +00:00
|
|
|
)
|
|
|
|
|
2022-10-26 20:27:24 +00:00
|
|
|
var generatorFlags = []cli.Flag{
|
2024-07-09 18:24:39 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "config",
|
|
|
|
Aliases: []string{"c"},
|
|
|
|
Usage: "Configuration file to use",
|
2022-10-26 20:27:24 +00:00
|
|
|
},
|
2024-07-09 18:24:39 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "manifest",
|
|
|
|
Aliases: []string{"m"},
|
2022-03-22 11:56:50 +00:00
|
|
|
Required: true,
|
|
|
|
Usage: "Read contract manifest (*.manifest.json) file",
|
2024-07-04 22:34:40 +00:00
|
|
|
Action: cmdargs.EnsureNotEmpty("manifest"),
|
2022-10-26 20:27:24 +00:00
|
|
|
},
|
2024-07-09 18:24:39 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "out",
|
|
|
|
Aliases: []string{"o"},
|
2022-03-22 11:56:50 +00:00
|
|
|
Required: true,
|
2022-12-28 09:18:09 +00:00
|
|
|
Usage: "Output of the compiled wrapper",
|
2024-07-04 22:34:40 +00:00
|
|
|
Action: cmdargs.EnsureNotEmpty("out"),
|
2022-10-26 20:27:24 +00:00
|
|
|
},
|
2024-07-09 18:24:39 +00:00
|
|
|
&cli.StringFlag{
|
2023-05-11 10:25:45 +00:00
|
|
|
Name: "hash",
|
2024-04-08 22:02:05 +00:00
|
|
|
Usage: "Smart-contract hash. If not passed, the wrapper will be designed for dynamic hash usage",
|
2022-10-26 20:27:24 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2024-07-09 18:24:39 +00:00
|
|
|
var generateWrapperCmd = &cli.Command{
|
2024-04-08 22:02:05 +00:00
|
|
|
Name: "generate-wrapper",
|
2024-07-03 12:35:18 +00:00
|
|
|
Usage: "Generate wrapper to use in other contracts",
|
2024-04-08 22:02:05 +00:00
|
|
|
UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
|
|
|
|
Description: `Generates a Go wrapper to use it in other smart contracts. If the
|
|
|
|
--hash flag is provided, CALLT instruction is used for the target contract
|
|
|
|
invocation as an optimization of the wrapper contract code. If omitted, the
|
|
|
|
generated wrapper will be designed for dynamic hash usage, allowing
|
|
|
|
the hash to be specified at runtime.
|
|
|
|
`,
|
|
|
|
Action: contractGenerateWrapper,
|
|
|
|
Flags: generatorFlags,
|
2022-10-26 20:27:24 +00:00
|
|
|
}
|
|
|
|
|
2024-07-09 18:24:39 +00:00
|
|
|
var generateRPCWrapperCmd = &cli.Command{
|
2022-10-26 20:27:24 +00:00
|
|
|
Name: "generate-rpcwrapper",
|
2024-07-03 12:35:18 +00:00
|
|
|
Usage: "Generate RPC wrapper to use for data reads",
|
2023-10-18 17:38:54 +00:00
|
|
|
UsageText: "neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
|
2022-10-26 20:27:24 +00:00
|
|
|
Action: contractGenerateRPCWrapper,
|
|
|
|
Flags: generatorFlags,
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func contractGenerateWrapper(ctx *cli.Context) error {
|
2024-04-08 22:02:05 +00:00
|
|
|
return contractGenerateSomething(ctx, binding.Generate)
|
2022-10-26 20:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func contractGenerateRPCWrapper(ctx *cli.Context) error {
|
2024-04-08 22:02:05 +00:00
|
|
|
return contractGenerateSomething(ctx, rpcbinding.Generate)
|
2022-10-26 20:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// contractGenerateSomething reads generator parameters and calls the given callback.
|
2024-04-08 22:02:05 +00:00
|
|
|
func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error) error {
|
2022-08-05 10:32:37 +00:00
|
|
|
if err := cmdargs.EnsureNone(ctx); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-05-11 10:25:45 +00:00
|
|
|
var (
|
|
|
|
h util.Uint160
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
if hStr := ctx.String("hash"); len(hStr) != 0 {
|
|
|
|
h, err = util.Uint160DecodeStringLE(strings.TrimPrefix(hStr, "0x"))
|
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("invalid contract hash: %w", err), 1)
|
2023-05-11 10:25:45 +00:00
|
|
|
}
|
2022-08-22 10:41:57 +00:00
|
|
|
}
|
|
|
|
m, _, err := readManifest(ctx.String("manifest"), h)
|
2021-10-25 11:48:21 +00:00
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("can't read contract manifest: %w", err), 1)
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cfg := binding.NewConfig()
|
|
|
|
if cfgPath := ctx.String("config"); cfgPath != "" {
|
2022-02-22 16:27:32 +00:00
|
|
|
bs, err := os.ReadFile(cfgPath)
|
2021-10-25 11:48:21 +00:00
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("can't read config file: %w", err), 1)
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
err = yaml.Unmarshal(bs, &cfg)
|
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("can't parse config file: %w", err), 1)
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cfg.Manifest = m
|
|
|
|
cfg.Hash = h
|
|
|
|
|
|
|
|
f, err := os.Create(ctx.String("out"))
|
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("can't create output file: %w", err), 1)
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
cfg.Output = f
|
|
|
|
|
2022-10-26 20:27:24 +00:00
|
|
|
err = cb(cfg)
|
2021-10-25 11:48:21 +00:00
|
|
|
if err != nil {
|
2024-07-09 18:24:39 +00:00
|
|
|
return cli.Exit(fmt.Errorf("error during generation: %w", err), 1)
|
2021-10-25 11:48:21 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|