package grpc import ( "fmt" "github.com/cosmos/cosmos-sdk/codec" "net" "time" "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/server/grpc/gogoreflection" reflection "github.com/cosmos/cosmos-sdk/server/grpc/reflection/v2alpha1" "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" ) // StartGRPCServer starts a gRPC server on the given address. func StartGRPCServer(clientCtx client.Context, app types.Application, address string) (*grpc.Server, error) { grpcSrv := grpc.NewServer( grpc.ForceServerCodec(codec.NewProtoCodec(clientCtx.InterfaceRegistry).GRPCCodec()), ) app.RegisterGRPCServer(grpcSrv) // reflection allows consumers to build dynamic clients that can write // to any cosmos-sdk application without relying on application packages at compile time err := reflection.Register(grpcSrv, reflection.Config{ SigningModes: func() map[string]int32 { modes := make(map[string]int32, len(clientCtx.TxConfig.SignModeHandler().Modes())) for _, m := range clientCtx.TxConfig.SignModeHandler().Modes() { modes[m.String()] = (int32)(m) } return modes }(), ChainID: clientCtx.ChainID, SdkConfig: sdk.GetConfig(), InterfaceRegistry: clientCtx.InterfaceRegistry, }) if err != nil { return nil, err } // Reflection allows external clients to see what services and methods // the gRPC server exposes. gogoreflection.Register(grpcSrv) listener, err := net.Listen("tcp", address) if err != nil { return nil, err } errCh := make(chan error) go func() { err = grpcSrv.Serve(listener) if err != nil { errCh <- fmt.Errorf("failed to serve: %w", err) } }() select { case err := <-errCh: return nil, err case <-time.After(types.ServerStartTime): // assume server started successfully return grpcSrv, nil } }