cli: allow to provide data for nep17 transfer commands

This commit is contained in:
Anna Shaleva 2021-04-16 13:45:54 +03:00
parent 28b74cb647
commit db868f033e
4 changed files with 55 additions and 10 deletions

View file

@ -161,6 +161,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) {

View file

@ -539,7 +539,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)
}
@ -624,12 +624,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]
@ -640,7 +640,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)
}
@ -888,6 +888,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{}

View file

@ -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)
}
}

View file

@ -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 <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string",
UsageText: "transfer --wallet <path> --rpc-endpoint <node> --timeout <time> --from <addr> --to <addr> --token <hash> --amount string [data]",
Action: transferNEP17,
Flags: transferFlags,
Description: `Transfers specified NEP17 token amount with optional 'data' parameter attached to the transfer.
See 'contract testinvokefunction' documentation for the details about 'data'
parameter. If no 'data' is given then default nil value will be used`,
},
{
Name: "multitransfer",
@ -459,11 +463,16 @@ func transferNEP17(ctx *cli.Context) error {
return cli.NewExitError(fmt.Errorf("invalid amount: %w", err), 1)
}
data, extErr := smartcontractcli.GetDataFromContext(ctx)
if extErr != nil {
return extErr
}
return signAndSendTransfer(ctx, c, acc, []client.TransferTarget{{
Token: token.Hash,
Address: to,
Amount: amount.Int64(),
Data: nil,
Data: data,
}})
}