func validateInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
	if err := xvalidator.Struct(req); err != nil {
		return nil, err
	}
	return handler(ctx, req)
}
TODO: could use github.com/grpc-ecosystem/go-grpc-middleware@v1.2.0/validator/validator.go for validating any request with a `Validate() error` function.
package grpc
import (
	"context"
	"net"
	"sync"
	"time"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_kit "github.com/grpc-ecosystem/go-grpc-middleware/logging/kit"
	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
	"github.com/mesg-foundation/engine/cosmos"
	"github.com/mesg-foundation/engine/event/publisher"
	"github.com/mesg-foundation/engine/ext/xvalidator"
	"github.com/mesg-foundation/engine/server/grpc/orchestrator"
	"github.com/mesg-foundation/engine/server/grpc/runner"
	tmlog "github.com/tendermint/tendermint/libs/log"
	"google.golang.org/grpc"
	"google.golang.org/grpc/keepalive"
	"google.golang.org/grpc/reflection"
)
type Server struct {
	instance          *grpc.Server
	rpc               *cosmos.RPC
	ep                *publisher.EventPublisher
	logger            tmlog.Logger
	authorizedPubKeys []string
}
func New(rpc *cosmos.RPC, ep *publisher.EventPublisher, logger tmlog.Logger, authorizedPubKeys []string) *Server {
	return &Server{
		rpc:               rpc,
		ep:                ep,
		logger:            logger.With("module", "grpc"),
		authorizedPubKeys: authorizedPubKeys,
	}
}
func (s *Server) Serve(address string) error {
	ln, err := net.Listen("tcp", address)
	if err != nil {
		return err
	}
	keepaliveOpt := grpc.KeepaliveParams(keepalive.ServerParameters{
		Time: 1 * time.Minute,
	})
	s.instance = grpc.NewServer(
		keepaliveOpt,
		grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
			grpc_kit.StreamServerInterceptor(newTmLogger(s.logger, "Served gRPC stream")),
			grpc_prometheus.StreamServerInterceptor,
		)),
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
			grpc_kit.UnaryServerInterceptor(newTmLogger(s.logger, "Served gRPC response")),
			grpc_prometheus.UnaryServerInterceptor,
			validateInterceptor,
		)),
	)
	if err := s.register(); err != nil {
		return err
	}
	grpc_prometheus.Register(s.instance)
	s.logger.Info("Server listens on " + ln.Addr().String())
	return s.instance.Serve(ln)
}
func (s *Server) Close() {
	s.instance.GracefulStop()
}