diff --git a/cli/nep17_test.go b/cli/nep17_test.go index 1f7b9c824..e74b1563e 100644 --- a/cli/nep17_test.go +++ b/cli/nep17_test.go @@ -158,6 +158,22 @@ func TestNEP17Transfer(t *testing.T) { b, _ = e.Chain.GetGoverningTokenBalance(sh) require.Equal(t, big.NewInt(41), b) }) + + t.Run("with data", func(t *testing.T) { + e.In.WriteString("one\r") + validTil := e.Chain.BlockHeight() + 100 + e.Run(t, []string{ + "neo-go", "wallet", "nep17", "transfer", + "--rpc-endpoint", "http://" + e.RPC.Addr, + "--wallet", validatorWallet, + "--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()), + "--token", "GAS", + "--amount", "1", + "--from", validatorAddr, + "[", validatorAddr, strconv.Itoa(int(validTil)), "]", + }...) + e.checkTxPersisted(t) + }) } func TestNEP17MultiTransfer(t *testing.T) { diff --git a/cli/smartcontract/smart_contract.go b/cli/smartcontract/smart_contract.go index 9436c4ad6..d7f7224fb 100644 --- a/cli/smartcontract/smart_contract.go +++ b/cli/smartcontract/smart_contract.go @@ -538,7 +538,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { paramsStart++ if len(args) > paramsStart { - cosignersOffset, params, err = parseParams(args[paramsStart:], true) + cosignersOffset, params, err = ParseParams(args[paramsStart:], true) if err != nil { return cli.NewExitError(err, 1) } @@ -623,12 +623,12 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error { return nil } -// parseParams extracts array of smartcontract.Parameter from the given args and +// ParseParams extracts array of smartcontract.Parameter from the given args and // returns the number of handled words, the array itself and an error. // `calledFromMain` denotes whether the method was called from the outside or // recursively and used to check if cosignersSeparator and closing bracket are // allowed to be in `args` sequence. -func parseParams(args []string, calledFromMain bool) (int, []smartcontract.Parameter, error) { +func ParseParams(args []string, calledFromMain bool) (int, []smartcontract.Parameter, error) { res := []smartcontract.Parameter{} for k := 0; k < len(args); { s := args[k] @@ -639,7 +639,7 @@ func parseParams(args []string, calledFromMain bool) (int, []smartcontract.Param } return 0, []smartcontract.Parameter{}, errors.New("invalid array syntax: missing closing bracket") case arrayStartSeparator: - numWordsRead, array, err := parseParams(args[k+1:], false) + numWordsRead, array, err := ParseParams(args[k+1:], false) if err != nil { return 0, nil, fmt.Errorf("failed to parse array: %w", err) } @@ -887,6 +887,26 @@ func contractDeploy(ctx *cli.Context) error { return nil } +// GetDataFromContext returns data parameter from context args. +func GetDataFromContext(ctx *cli.Context) (interface{}, *cli.ExitError) { + var data interface{} + args := ctx.Args() + if args.Present() { + _, params, err := ParseParams(args, true) + if err != nil { + return nil, cli.NewExitError(fmt.Errorf("unable to parse 'data' parameter: %w", err), 1) + } + if len(params) != 1 { + return nil, cli.NewExitError("'data' should be represented as a single parameter", 1) + } + data, err = smartcontract.ExpandParameterToEmitable(params[0]) + if err != nil { + return nil, cli.NewExitError(fmt.Sprintf("failed to convert 'data' to emitable type: %s", err.Error()), 1) + } + } + return data, nil +} + // ParseContractConfig reads contract configuration file (.yaml) and returns unmarshalled ProjectConfig. func ParseContractConfig(confFile string) (ProjectConfig, error) { conf := ProjectConfig{} diff --git a/cli/smartcontract/smart_contract_test.go b/cli/smartcontract/smart_contract_test.go index 64e8811fb..89af4f7be 100644 --- a/cli/smartcontract/smart_contract_test.go +++ b/cli/smartcontract/smart_contract_test.go @@ -202,7 +202,7 @@ func TestParseParams_CalledFromItself(t *testing.T) { for str, expected := range testCases { input := strings.Split(str, " ") - offset, actual, err := parseParams(input, false) + offset, actual, err := ParseParams(input, false) require.NoError(t, err) require.Equal(t, expected.WordsRead, offset) require.Equal(t, expected.Value, actual) @@ -218,7 +218,7 @@ func TestParseParams_CalledFromItself(t *testing.T) { for _, str := range errorCases { input := strings.Split(str, " ") - _, _, err := parseParams(input, false) + _, _, err := ParseParams(input, false) require.Error(t, err) } } @@ -400,7 +400,7 @@ func TestParseParams_CalledFromOutside(t *testing.T) { } for str, expected := range testCases { input := strings.Split(str, " ") - offset, arr, err := parseParams(input, true) + offset, arr, err := ParseParams(input, true) require.NoError(t, err) require.Equal(t, expected.WordsRead, offset) require.Equal(t, expected.Parameters, arr) @@ -415,7 +415,7 @@ func TestParseParams_CalledFromOutside(t *testing.T) { } for _, str := range errorCases { input := strings.Split(str, " ") - _, _, err := parseParams(input, true) + _, _, err := ParseParams(input, true) require.Error(t, err) } } diff --git a/cli/wallet/nep17.go b/cli/wallet/nep17.go index a2185946a..70817a15b 100644 --- a/cli/wallet/nep17.go +++ b/cli/wallet/nep17.go @@ -9,6 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/cli/flags" "github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/cli/paramcontext" + smartcontractcli "github.com/nspcc-dev/neo-go/cli/smartcontract" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpc/client" @@ -111,9 +112,12 @@ func newNEP17Commands() []cli.Command { { Name: "transfer", Usage: "transfer NEP17 tokens", - UsageText: "transfer --wallet --rpc-endpoint --timeout