diff --git a/x/move/client/cli/query.go b/x/move/client/cli/query.go index cc3b8761..c74f8185 100644 --- a/x/move/client/cli/query.go +++ b/x/move/client/cli/query.go @@ -12,6 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/initia-labs/initia/x/move/types" + vmapi "github.com/initia-labs/initiavm/api" ) func GetQueryCmd() *cobra.Command { @@ -30,6 +31,7 @@ func GetQueryCmd() *cobra.Command { GetCmdTableEntry(), GetCmdTableEntries(), GetCmdQueryEntryFunction(), + GetCmdQueryParams(), ) return queryCmd } @@ -124,7 +126,8 @@ func GetCmdResource() *cobra.Command { return err } - if err := sdk.ValidateDenom(args[1]); err != nil { + _, err = vmapi.ParseStructTag(args[1]) + if err != nil { return err } @@ -276,6 +279,7 @@ func GetCmdQueryEntryFunction() *cobra.Command { Get an entry function execution result Supported types : u8, u16, u32, u64, u128, u256, bool, string, address, raw, vector + Example of args: address:0x1 bool:true u8:0 string:hello vector:a,b,c,d Example: @@ -284,7 +288,7 @@ $ %s query 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, ), ), @@ -310,29 +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, " ") - } - 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) } queryClient := types.NewQueryClient(clientCtx) @@ -358,3 +358,39 @@ $ %s query move execute \ flags.AddQueryFlagsToCmd(cmd) return cmd } + +// GetCmdQueryParams implements the params query command. +func GetCmdQueryParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Args: cobra.NoArgs, + Short: "Query the current move parameters information", + Long: strings.TrimSpace( + fmt.Sprintf(`Query values set as move parameters. + +Example: +$ %s query move params +`, + version.AppName, + ), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(&res.Params) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} 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"},