diff --git a/x/move/client/cli/query.go b/x/move/client/cli/query.go index 9cd27246..c74f8185 100644 --- a/x/move/client/cli/query.go +++ b/x/move/client/cli/query.go @@ -279,7 +279,6 @@ func GetCmdQueryEntryFunction() *cobra.Command { Get an entry function execution result Supported types : u8, u16, u32, u64, u128, u256, bool, string, address, raw, vector -string can be quoted with double quotation marks. Example of args: address:0x1 bool:true u8:0 string:hello vector:a,b,c,d @@ -315,58 +314,25 @@ $ %s query move execute \ typeArgs = strings.Split(flagTypeArgs, " ") } - var flagArgsList []string flagArgs, err := cmd.Flags().GetString(FlagArgs) if err != nil { return err } - if flagArgs != "" { - flagArgsList = strings.Split(flagArgs, " ") + + argTypes, args := parseArguments(flagArgs) + if len(argTypes) != len(args) { + return fmt.Errorf("invalid argument format len(types) != len(args)") } - bcsArgs := [][]byte{} - strval := "" - inConcat := false serializer := NewSerializer() - for _, v := range flagArgsList { - if !inConcat { - arg := strings.Split(v, ":") - if len(arg) != 2 || arg[0] == "" || arg[1] == "" { - return fmt.Errorf("invalid argument format: %s", arg) - } - - if arg[0] == "string" { - if arg[1][0] == '"' { - arg[1] = arg[1][1:] - if arg[1][len(arg[1])-1] == '"' { - arg[1] = arg[1][:len(arg[1])-1] - } else { - strval = arg[1] - inConcat = true - } - } - } - - bcsArg, err := BcsSerializeArg(arg[0], arg[1], serializer) - if err != nil { - return err - } - bcsArgs = append(bcsArgs, bcsArg) - } else { - if v[len(v)-1] == '"' { - strval += (" " + v[:len(v)-1]) - inConcat = false - bcsArg, err := BcsSerializeArg("string", strval, serializer) - if err != nil { - return err - } - bcsArgs = append(bcsArgs, bcsArg) - strval = "" - } else { - strval += (" " + v) // recover space - } + bcsArgs := [][]byte{} + for i := range argTypes { + bcsArg, err := BcsSerializeArg(argTypes[i], args[i], serializer) + if err != nil { + return err } + bcsArgs = append(bcsArgs, bcsArg) } queryClient := types.NewQueryClient(clientCtx) diff --git a/x/move/client/cli/tx.go b/x/move/client/cli/tx.go index 4ab9d2f2..24a03141 100644 --- a/x/move/client/cli/tx.go +++ b/x/move/client/cli/tx.go @@ -117,7 +117,7 @@ $ %s tx move execute \ BasicCoin \ getBalance \ --type-args '0x1::native_uinit::Coin 0x1::native_uusdc::Coin' \ - --args 'u8:0 address:0x1' + --args 'u8:0 address:0x1 string:"hello world"' `, version.AppName, bech32PrefixAccAddr, ), ), @@ -142,29 +142,25 @@ $ %s tx move execute \ typeArgs = strings.Split(flagTypeArgs, " ") } - var flagArgsList []string flagArgs, err := cmd.Flags().GetString(FlagArgs) if err != nil { return err } - if flagArgs != "" { - flagArgsList = strings.Split(flagArgs, " ") - } - bcsArgs := make([][]byte, len(flagArgsList)) - for i, arg := range flagArgsList { - argSplit := strings.Split(arg, ":") - if len(argSplit) != 2 { - return fmt.Errorf("invalid argument format: %s", arg) - } + argTypes, args := parseArguments(flagArgs) + if len(argTypes) != len(args) { + return fmt.Errorf("invalid argument format len(types) != len(args)") + } - serializer := NewSerializer() - bcsArg, err := BcsSerializeArg(argSplit[0], argSplit[1], serializer) + serializer := NewSerializer() + bcsArgs := [][]byte{} + for i := range argTypes { + bcsArg, err := BcsSerializeArg(argTypes[i], args[i], serializer) if err != nil { return err } - bcsArgs[i] = bcsArg + bcsArgs = append(bcsArgs, bcsArg) } msg := types.MsgExecute{ diff --git a/x/move/client/cli/utils.go b/x/move/client/cli/utils.go index eb78871e..e6052b29 100644 --- a/x/move/client/cli/utils.go +++ b/x/move/client/cli/utils.go @@ -239,3 +239,60 @@ func DivideUint256String(s string) (uint64, uint64, uint64, uint64, error) { highHigh := n.Rsh(n, 64).Uint64() return highHigh, highLow, high, low, nil } + +func parseArguments(s string) (tt []string, args []string) { + cursor := 0 + + var t, a string + var typeParsing, quoteParsing bool + + typeParsing = true + for len(s) > cursor { + c := s[cursor] + if c == ':' { + typeParsing = false + + cursor++ + continue + } else if quoteParsing { + if c == '"' { + quoteParsing = false + + cursor++ + continue + } + } else { + if c == ' ' { + typeParsing = true + + tt = append(tt, t) + args = append(args, a) + + t = "" + a = "" + + cursor++ + continue + } else if c == '"' { + typeParsing = false + quoteParsing = true + + cursor++ + continue + } + } + + if typeParsing { + t += string(c) + } else { + a += string(c) + } + + cursor++ + } + + tt = append(tt, t) + args = append(args, a) + + return +} diff --git a/x/move/client/cli/utils_test.go b/x/move/client/cli/utils_test.go index b9cb73e9..cc86244b 100644 --- a/x/move/client/cli/utils_test.go +++ b/x/move/client/cli/utils_test.go @@ -6,6 +6,12 @@ import ( "github.com/stretchr/testify/require" ) +func Test_parseArguments(t *testing.T) { + argTypes, args := parseArguments("u8:1 u16:256 string:\"hello world\" string:\"hello\" vector:\"hello world\",\"hello world\" vector:true,false,true") + require.Equal(t, []string{"u8", "u16", "string", "string", "vector", "vector"}, argTypes) + require.Equal(t, []string{"1", "256", "hello world", "hello", "hello world,hello world", "true,false,true"}, args) +} + func Test_BcsSerializeArg(t *testing.T) { testCases := []struct { @@ -55,6 +61,7 @@ func Test_BcsSerializeArg(t *testing.T) { {"vector", "65536,65536,-1", nil, true, "vector 65536,65536,-1"}, {"vector
", "0x1,0x2,0x3", []byte{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3}, false, "vector
0x1,0x2,0x3"}, {"vector", "hello,world", []byte{0x2, 0x5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x5, 0x77, 0x6f, 0x72, 0x6c, 0x64}, false, "vector hello,world"}, + {"vector", "hello world,hello world", []byte{0x2, 0xb, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0xb, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64}, false, "vector \"hello world,hello world\""}, {"vector", "", []byte{0}, false, "vector empty"}, {"vector", "0", []byte{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, false, "vector 0"}, {"vector", "1", []byte{0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, false, "vector 1"},