88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/iancoleman/strcase"
|
|
"github.com/spf13/cobra"
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client/v2/cli/flag"
|
|
"github.com/cosmos/cosmos-sdk/client/v2/internal/util"
|
|
)
|
|
|
|
// AddQueryServiceCommands adds a sub-command to the provided command for each
|
|
// method in the specified service and returns the command.
|
|
func (b *Builder) AddQueryServiceCommands(command *cobra.Command, serviceName protoreflect.FullName) *cobra.Command {
|
|
resolver := b.FileResolver
|
|
if resolver == nil {
|
|
resolver = protoregistry.GlobalFiles
|
|
}
|
|
descriptor, err := resolver.FindDescriptorByName(serviceName)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
service := descriptor.(protoreflect.ServiceDescriptor)
|
|
methods := service.Methods()
|
|
n := methods.Len()
|
|
for i := 0; i < n; i++ {
|
|
cmd := b.CreateQueryMethodCommand(methods.Get(i))
|
|
command.AddCommand(cmd)
|
|
}
|
|
return command
|
|
}
|
|
|
|
// CreateQueryMethodCommand creates a gRPC query command for the given service method.
|
|
func (b *Builder) CreateQueryMethodCommand(descriptor protoreflect.MethodDescriptor) *cobra.Command {
|
|
serviceDescriptor := descriptor.Parent().(protoreflect.ServiceDescriptor)
|
|
docs := util.DescriptorDocs(descriptor)
|
|
getClientConn := b.GetClientConn
|
|
methodName := fmt.Sprintf("/%s/%s", serviceDescriptor.FullName(), descriptor.Name())
|
|
|
|
inputDesc := descriptor.Input()
|
|
inputType := util.ResolveMessageType(b.TypeResolver, inputDesc)
|
|
outputType := util.ResolveMessageType(b.TypeResolver, descriptor.Output())
|
|
cmd := &cobra.Command{
|
|
Use: protoNameToCliName(descriptor.Name()),
|
|
Long: docs,
|
|
}
|
|
|
|
binder := b.AddMessageFlags(cmd.Context(), cmd.Flags(), inputType, flag.Options{})
|
|
|
|
jsonMarshalOptions := protojson.MarshalOptions{
|
|
Indent: " ",
|
|
UseProtoNames: true,
|
|
UseEnumNumbers: false,
|
|
EmitUnpopulated: true,
|
|
Resolver: b.TypeResolver,
|
|
}
|
|
|
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Context()
|
|
clientConn := getClientConn(ctx)
|
|
input := binder.BuildMessage()
|
|
output := outputType.New()
|
|
err := clientConn.Invoke(ctx, methodName, input.Interface(), output.Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
bz, err := jsonMarshalOptions.Marshal(output.Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = fmt.Fprintln(cmd.OutOrStdout(), string(bz))
|
|
return err
|
|
}
|
|
|
|
return cmd
|
|
}
|
|
|
|
func protoNameToCliName(name protoreflect.Name) string {
|
|
return strcase.ToKebab(string(name))
|
|
}
|