cosmos-sdk/simapp/v2/simdv2/cmd/commands.go

281 lines
7.6 KiB
Go

package cmd
import (
"context"
"io"
"github.com/spf13/cobra"
"cosmossdk.io/client/v2/offchain"
coreserver "cosmossdk.io/core/server"
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
runtimev2 "cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
grpcserver "cosmossdk.io/server/v2/api/grpc"
"cosmossdk.io/server/v2/api/grpcgateway"
"cosmossdk.io/server/v2/api/rest"
"cosmossdk.io/server/v2/api/swagger"
"cosmossdk.io/server/v2/api/telemetry"
"cosmossdk.io/server/v2/cometbft"
serverstore "cosmossdk.io/server/v2/store"
"cosmossdk.io/simapp/v2"
confixcmd "cosmossdk.io/tools/confix/cmd"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/docs"
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
sdktelemetry "github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/version"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
v2 "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli"
)
// CommandDependencies is a struct that contains all the dependencies needed to initialize the root command.
// an alternative design could fetch these even later from the command context
type CommandDependencies[T transaction.Tx] struct {
GlobalConfig coreserver.ConfigMap
TxConfig client.TxConfig
ModuleManager *runtimev2.MM[T]
SimApp *simapp.SimApp[T]
ClientContext client.Context
}
func InitRootCmd[T transaction.Tx](
rootCmd *cobra.Command,
logger log.Logger,
deps CommandDependencies[T],
) (serverv2.ConfigWriter, error) {
cfg := sdk.GetConfig()
cfg.Seal()
rootCmd.AddCommand(
genutilcli.InitCmd(deps.ModuleManager),
genesisCommand(deps.ModuleManager, deps.SimApp),
NewTestnetCmd(deps.ModuleManager),
debug.Cmd(),
confixcmd.ConfigCommand(),
// add keybase, auxiliary RPC, query, genesis, and tx child commands
queryCommand(),
txCommand(),
keys.Commands(),
offchain.OffChain(),
version.NewVersionCommand(),
)
// build CLI skeleton for initial config parsing or a client application invocation
if deps.SimApp == nil {
return serverv2.AddCommands[T](
rootCmd,
logger,
io.NopCloser(nil),
deps.GlobalConfig,
initServerConfig(),
cometbft.NewWithConfigOptions[T](initCometConfig()),
&grpcserver.Server[T]{},
&serverstore.Server[T]{},
&telemetry.Server[T]{},
&rest.Server[T]{},
&grpcgateway.Server[T]{},
&swagger.Server[T]{},
)
}
// build full app!
simApp := deps.SimApp
// store component (not a server)
storeComponent, err := serverstore.New[T](simApp.Store(), deps.GlobalConfig)
if err != nil {
return nil, err
}
restServer, err := rest.New[T](logger, simApp.App.AppManager, deps.GlobalConfig)
if err != nil {
return nil, err
}
// consensus component
consensusServer, err := cometbft.New(
logger,
simApp.Name(),
simApp.Store(),
simApp.App.AppManager,
cometbft.AppCodecs[T]{
AppCodec: simApp.AppCodec(),
TxCodec: &client.DefaultTxDecoder[T]{TxConfig: deps.TxConfig},
LegacyAmino: deps.ClientContext.LegacyAmino,
ConsensusAddressCodec: deps.ClientContext.ConsensusAddressCodec,
},
simApp.App.QueryHandlers(),
simApp.App.SchemaDecoderResolver(),
initCometOptions[T](),
deps.GlobalConfig,
)
if err != nil {
return nil, err
}
telemetryServer, err := telemetry.New[T](logger, sdktelemetry.EnableTelemetry, deps.GlobalConfig)
if err != nil {
return nil, err
}
swaggerServer, err := swagger.New[T](logger, docs.GetSwaggerFS(), deps.GlobalConfig)
if err != nil {
return nil, err
}
grpcServer, err := grpcserver.New[T](
logger,
simApp.InterfaceRegistry(),
simApp.QueryHandlers(),
simApp.Query,
deps.GlobalConfig,
grpcserver.WithExtraGRPCHandlers[T](
consensusServer.GRPCServiceRegistrar(
deps.ClientContext,
deps.GlobalConfig,
),
),
)
if err != nil {
return nil, err
}
grpcgatewayServer, err := grpcgateway.New[T](
logger,
deps.GlobalConfig,
simApp.InterfaceRegistry(),
simApp.App.AppManager,
)
if err != nil {
return nil, err
}
registerGRPCGatewayRoutes(deps.ClientContext, grpcgatewayServer)
// wire server commands
return serverv2.AddCommands[T](
rootCmd,
logger,
simApp,
deps.GlobalConfig,
initServerConfig(),
consensusServer,
grpcServer,
storeComponent,
telemetryServer,
restServer,
grpcgatewayServer,
swaggerServer,
)
}
// genesisCommand builds genesis-related `simd genesis` command.
func genesisCommand[T transaction.Tx](
moduleManager *runtimev2.MM[T],
app *simapp.SimApp[T],
) *cobra.Command {
var genTxValidator func([]transaction.Msg) error
if moduleManager != nil {
genTxValidator = moduleManager.Modules()[genutiltypes.ModuleName].(genutil.AppModule).GenTxValidator()
}
cmd := v2.Commands(
genTxValidator,
moduleManager,
app,
)
return cmd
}
func queryCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"},
Short: "Querying subcommands",
DisableFlagParsing: false,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
rpc.QueryEventForTxCmd(),
authcmd.QueryTxsByEventsCmd(),
authcmd.QueryTxCmd(),
)
return cmd
}
func txCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
DisableFlagParsing: false,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
authcmd.GetSignCommand(),
authcmd.GetSignBatchCommand(),
authcmd.GetMultiSignCommand(),
authcmd.GetMultiSignBatchCmd(),
authcmd.GetValidateSignaturesCommand(),
authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(),
authcmd.GetSimulateCmd(),
)
return cmd
}
func RootCommandPersistentPreRun(clientCtx client.Context) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
// set the default command outputs
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
clientCtx = clientCtx.WithCmdContext(cmd.Context())
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
if err != nil {
return err
}
customClientTemplate, customClientConfig := initClientConfig()
clientCtx, err = config.CreateClientConfig(
clientCtx, customClientTemplate, customClientConfig)
if err != nil {
return err
}
if err = client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
return err
}
return nil
}
}
// registerGRPCGatewayRoutes registers the gRPC gateway routes for all modules and other components
func registerGRPCGatewayRoutes[T transaction.Tx](
clientContext client.Context,
server *grpcgateway.Server[T],
) {
// those are the extra services that the CometBFT server implements (server/v2/cometbft/grpc.go)
cmtservice.RegisterGRPCGatewayRoutes(clientContext, server.GRPCGatewayRouter)
_ = nodeservice.RegisterServiceHandlerClient(context.Background(), server.GRPCGatewayRouter, nodeservice.NewServiceClient(clientContext))
_ = txtypes.RegisterServiceHandlerClient(context.Background(), server.GRPCGatewayRouter, txtypes.NewServiceClient(clientContext))
}