Synopsis

This document describes the core parts of a Cosmos SDK application, represented throughout the document as a placeholder application named app.

Node Client

The Daemon, or Full-Node Client, is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes, and update their state-machine as new blocks come in.
                ^  +-------------------------------+  ^
                |  |                               |  |
                |  |  State-machine = Application  |  |
                |  |                               |  |   Built with Cosmos SDK
                |  |            ^      +           |  |
                |  +----------- | ABCI | ----------+  v
                |  |            +      v           |  ^
                |  |                               |  |
Blockchain Node |  |           Consensus           |  |
                |  |                               |  |
                |  +-------------------------------+  |   CometBFT
                |  |                               |  |
                |  |           Networking          |  |
                |  |                               |  |
                v  +-------------------------------+  v
The blockchain full-node presents itself as a binary, generally suffixed by -d for “daemon” (e.g. appd for app or gaiad for gaia). This binary is built by running a simple main.go function placed in ./cmd/appd/. This operation usually happens through the Makefile. Once the main binary is built, the node can be started by running the start command. This command function primarily does three things:
  1. Create an instance of the state-machine defined in app.go.
  2. Initialize the state-machine with the latest known state, extracted from the db stored in the ~/.app/data folder. At this point, the state-machine is at height appBlockHeight.
  3. Create and start a new CometBFT instance. Among other things, the node performs a handshake with its peers. It gets the latest blockHeight from them and replays blocks to sync to this height if it is greater than the local appBlockHeight. The node starts from genesis and CometBFT sends an InitChain message via the ABCI to the app, which triggers the InitChainer.
When starting a CometBFT instance, the genesis file is the 0 height and the state within the genesis file is committed at block height 1. When querying the state of the node, querying block height 0 will return an error.

Core Application File

In general, the core of the state-machine is defined in a file called app.go. This file mainly contains the type definition of the application and functions to create and initialize it.

Type Definition of the Application

The first thing defined in app.go is the type of the application. It is generally comprised of the following parts:
  • Embeding runtime.App The runtime package manages the application’s core components and modules through dependency injection. It provides declarative configuration for module management, state storage, and ABCI handling.
  • An App Wiring configuration file The app wiring configuration file contains the list of application’s modules that runtime must instantiate. The instantiation of the modules are done using depinject. It also contains the order in which all module’s InitGenesis and Pre/Begin/EndBlocker methods should be executed.
  • A reference to an appCodec. The application’s appCodec is used to serialize and deserialize data structures in order to store them, as stores can only persist []bytes. The default codec is Protocol Buffers.
  • A reference to a legacyAmino codec. Some parts of the Cosmos SDK have not been migrated to use the appCodec above, and are still hardcoded to use Amino. Other parts explicitly use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases.
See an example of application type definition from simapp, the Cosmos SDK’s own app used for demo and testing purposes:
/go:build !app_v1

package simapp

import (

	"io"

	dbm "github.com/cosmos/cosmos-db"

	clienthelpers "cosmossdk.io/client/v2/helpers"
    "cosmossdk.io/depinject"
    "cosmossdk.io/log"
	storetypes "cosmossdk.io/store/types"
	circuitkeeper "cosmossdk.io/x/circuit/keeper"
	evidencekeeper "cosmossdk.io/x/evidence/keeper"
	feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
	nftkeeper "cosmossdk.io/x/nft/keeper"
	upgradekeeper "cosmossdk.io/x/upgrade/keeper"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/runtime"
    "github.com/cosmos/cosmos-sdk/server"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
	testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
    "github.com/cosmos/cosmos-sdk/types/module"
    "github.com/cosmos/cosmos-sdk/x/auth"
    "github.com/cosmos/cosmos-sdk/x/auth/ante"
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
	authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
	distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
	epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
	groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
	mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
	protocolpoolkeeper "github.com/cosmos/cosmos-sdk/x/protocolpool/keeper"
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
)

/ DefaultNodeHome default home directories for the application daemon
var DefaultNodeHome string

var (
	_ runtime.AppI            = (*SimApp)(nil)
	_ servertypes.Application = (*SimApp)(nil)
)

/ SimApp extends an ABCI application, but with most of its parameters exported.
/ They are exported for convenience in creating helper functions, as object
/ capabilities aren't needed for testing.
type SimApp struct {
	*runtime.App
	legacyAmino       *codec.LegacyAmino
	appCodec          codec.Codec
	txConfig          client.TxConfig
	interfaceRegistry codectypes.InterfaceRegistry

	/ essential keepers
	AccountKeeper         authkeeper.AccountKeeper
	BankKeeper            bankkeeper.BaseKeeper
	StakingKeeper         *stakingkeeper.Keeper
	SlashingKeeper        slashingkeeper.Keeper
	MintKeeper            mintkeeper.Keeper
	DistrKeeper           distrkeeper.Keeper
	GovKeeper             *govkeeper.Keeper
	UpgradeKeeper         *upgradekeeper.Keeper
	EvidenceKeeper        evidencekeeper.Keeper
	ConsensusParamsKeeper consensuskeeper.Keeper
	CircuitKeeper         circuitkeeper.Keeper

	/ supplementary keepers
	FeeGrantKeeper     feegrantkeeper.Keeper
	GroupKeeper        groupkeeper.Keeper
	AuthzKeeper        authzkeeper.Keeper
	NFTKeeper          nftkeeper.Keeper
	EpochsKeeper       epochskeeper.Keeper
	ProtocolPoolKeeper protocolpoolkeeper.Keeper

	/ simulation manager
	sm *module.SimulationManager
}

func init() {
    var err error
	DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
    if err != nil {
    panic(err)
}
}

/ NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
	baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    var (
		app        = &SimApp{
}

appBuilder *runtime.AppBuilder

		/ merge the AppConfig and other configuration in one config
		appConfig = depinject.Configs(
			AppConfig,
			depinject.Supply(
				/ supply the application options
				appOpts,
				/ supply the logger
				logger,

				/ ADVANCED CONFIGURATION

				/
				/ AUTH
				/
				/ For providing a custom function required in auth to generate custom account types
				/ add it below. By default the auth module uses simulation.RandomGenesisAccounts.
				/
				/ authtypes.RandomGenesisAccountsFn(simulation.RandomGenesisAccounts),
				/
				/ For providing a custom a base account type add it below.
				/ By default the auth module uses authtypes.ProtoBaseAccount().
				/
				/ func()

sdk.AccountI {
    return authtypes.ProtoBaseAccount()
},
				/
				/ For providing a different address codec, add it below.
				/ By default the auth module uses a Bech32 address codec,
				/ with the prefix defined in the auth module configuration.
				/
				/ func()

address.Codec {
    return <- custom address codec type ->
}
				/
				/ STAKING
				/
				/ For provinding a different validator and consensus address codec, add it below.
				/ By default the staking module uses the bech32 prefix provided in the auth config,
				/ and appends "valoper" and "valcons" for validator and consensus addresses respectively.
				/ When providing a custom address codec in auth, custom address codecs must be provided here as well.
				/
				/ func()

runtime.ValidatorAddressCodec {
    return <- custom validator address codec type ->
}
				/ func()

runtime.ConsensusAddressCodec {
    return <- custom consensus address codec type ->
}

				/
				/ MINT
				/

				/ For providing a custom inflation function for x/mint add here your
				/ custom minting function that implements the mintkeeper.MintFn
				/ interface.
			),
		)
	)
    if err := depinject.Inject(appConfig,
		&appBuilder,
		&app.appCodec,
		&app.legacyAmino,
		&app.txConfig,
		&app.interfaceRegistry,
		&app.AccountKeeper,
		&app.BankKeeper,
		&app.StakingKeeper,
		&app.SlashingKeeper,
		&app.MintKeeper,
		&app.DistrKeeper,
		&app.GovKeeper,
		&app.UpgradeKeeper,
		&app.AuthzKeeper,
		&app.EvidenceKeeper,
		&app.FeeGrantKeeper,
		&app.GroupKeeper,
		&app.NFTKeeper,
		&app.ConsensusParamsKeeper,
		&app.CircuitKeeper,
		&app.EpochsKeeper,
		&app.ProtocolPoolKeeper,
	); err != nil {
    panic(err)
}

	/ Below we could construct and set an application specific mempool and
	/ ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
	/ already set in the SDK's BaseApp, this shows an example of how to override
	/ them.
	/
	/ Example:
	/
	/ app.App = appBuilder.Build(...)
	/ nonceMempool := mempool.NewSenderNonceMempool()
	/ abciPropHandler := NewDefaultProposalHandler(nonceMempool, app.App.BaseApp)
	/
	/ app.App.BaseApp.SetMempool(nonceMempool)
	/ app.App.BaseApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/ app.App.BaseApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
	/
	/ Alternatively, you can construct BaseApp options, append those to
	/ baseAppOptions and pass them to the appBuilder.
	/
	/ Example:
	/
	/ prepareOpt = func(app *baseapp.BaseApp) {
	/ 	abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
	/ 	app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/
}
	/ baseAppOptions = append(baseAppOptions, prepareOpt)

	/ create and set dummy vote extension handler
    voteExtOp := func(bApp *baseapp.BaseApp) {
    voteExtHandler := NewVoteExtensionHandler()

voteExtHandler.SetHandlers(bApp)
}

baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())

app.App = appBuilder.Build(db, traceStore, baseAppOptions...)

	/ register streaming services
    if err := app.RegisterStreamingServices(appOpts, app.kvStoreKeys()); err != nil {
    panic(err)
}

	/****  Module Options ****/

	/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
	app.RegisterUpgradeHandlers()

	/ add test gRPC service for testing gRPC queries in isolation
	testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{
})

	/ create the simulation manager and define the order of the modules for deterministic simulations
	/
	/ NOTE: this is not required apps that don't use the simulator for fuzz testing
	/ transactions
    overrideModules := map[string]module.AppModuleSimulation{
    authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}

app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

	/ A custom InitChainer can be set if extra pre-init-genesis logic is required.
	/ By default, when using app wiring enabled module, this is not required.
	/ For instance, the upgrade module will set automatically the module version map in its init genesis thanks to app wiring.
	/ However, when registering a module manually (i.e. that does not support app wiring), the module version map
	/ must be set manually as follow. The upgrade module will de-duplicate the module version map.
	/
	/ app.SetInitChainer(func(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
	/ 	app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())
	/ 	return app.App.InitChainer(ctx, req)
	/
})

	/ set custom ante handler
	app.setAnteHandler(app.txConfig)
    if err := app.Load(loadLatest); err != nil {
    panic(err)
}

return app
}

/ setAnteHandler sets custom ante handlers.
/ "x/auth/tx" pre-defined ante handler have been disabled in app_config.
func (app *SimApp)

setAnteHandler(txConfig client.TxConfig) {
    anteHandler, err := NewAnteHandler(
		HandlerOptions{
    ante.HandlerOptions{
    AccountKeeper:   app.AccountKeeper,
    BankKeeper:      app.BankKeeper,
    SignModeHandler: txConfig.SignModeHandler(),
    FeegrantKeeper:  app.FeeGrantKeeper,
    SigGasConsumer:  ante.DefaultSigVerificationGasConsumer,
},
			&app.CircuitKeeper,
},
	)
    if err != nil {
    panic(err)
}

	/ Set the AnteHandler for the app
	app.SetAnteHandler(anteHandler)
}

/ LegacyAmino returns SimApp's amino codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

LegacyAmino() *codec.LegacyAmino {
    return app.legacyAmino
}

/ AppCodec returns SimApp's app codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

AppCodec()

codec.Codec {
    return app.appCodec
}

/ InterfaceRegistry returns SimApp's InterfaceRegistry.
func (app *SimApp)

InterfaceRegistry()

codectypes.InterfaceRegistry {
    return app.interfaceRegistry
}

/ TxConfig returns SimApp's TxConfig
func (app *SimApp)

TxConfig()

client.TxConfig {
    return app.txConfig
}

/ GetKey returns the KVStoreKey for the provided store key.
/
/ NOTE: This is solely to be used for testing purposes.
func (app *SimApp)

GetKey(storeKey string) *storetypes.KVStoreKey {
    sk := app.UnsafeFindStoreKey(storeKey)

kvStoreKey, ok := sk.(*storetypes.KVStoreKey)
    if !ok {
    return nil
}

return kvStoreKey
}

func (app *SimApp)

kvStoreKeys()

map[string]*storetypes.KVStoreKey {
    keys := make(map[string]*storetypes.KVStoreKey)
    for _, k := range app.GetStoreKeys() {
    if kv, ok := k.(*storetypes.KVStoreKey); ok {
    keys[kv.Name()] = kv
}

}

return keys
}

/ SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}

/ RegisterAPIRoutes registers all application module routes with the provided
/ API server.
func (app *SimApp)

RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    app.App.RegisterAPIRoutes(apiSvr, apiConfig)
	/ register swagger API in app.go so that other applications can override easily
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
}
}

/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()

map[string][]string {
    dup := make(map[string][]string)
    for _, perms := range moduleAccPerms {
    dup[perms.Account] = perms.Permissions
}

return dup
}

/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()

map[string]bool {
    result := make(map[string]bool)
    if len(blockAccAddrs) > 0 {
    for _, addr := range blockAccAddrs {
    result[addr] = true
}

}

else {
    for addr := range GetMaccPerms() {
    result[addr] = true
}

}

return result
}

Constructor Function

Also defined in app.go is the constructor function, which constructs a new application of the type defined in the preceding section. The function must fulfill the AppCreator signature in order to be used in the start command of the application’s daemon command.
package types

import (

	"encoding/json"
    "io"

	cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
	cmttypes "github.com/cometbft/cometbft/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/cosmos/gogoproto/grpc"
    "github.com/spf13/cobra"
    "cosmossdk.io/log"
    "cosmossdk.io/store/snapshots"
	storetypes "cosmossdk.io/store/types"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
)

type (
	/ AppOptions defines an interface that is passed into an application
	/ constructor, typically used to set BaseApp options that are either supplied
	/ via config file or through CLI arguments/flags. The underlying implementation
	/ is defined by the server package and is typically implemented via a Viper
	/ literal defined on the server Context. Note, casting Get calls may not yield
	/ the expected types and could result in type assertion errors. It is recommend
	/ to either use the cast package or perform manual conversion for safety.
	AppOptions interface {
    Get(string)

any
}

	/ Application defines an application interface that wraps abci.Application.
	/ The interface defines the necessary contracts to be implemented in order
	/ to fully bootstrap and start an application.
	Application interface {
    ABCI

		RegisterAPIRoutes(*api.Server, config.APIConfig)

		/ RegisterGRPCServerWithSkipCheckHeader registers gRPC services directly with the gRPC
		/ server and bypass check header flag.
		RegisterGRPCServerWithSkipCheckHeader(grpc.Server, bool)

		/ RegisterTxService registers the gRPC Query service for tx (such as tx
		/ simulation, fetching txs by hash...).
		RegisterTxService(client.Context)

		/ RegisterTendermintService registers the gRPC Query service for CometBFT queries.
		RegisterTendermintService(client.Context)

		/ RegisterNodeService registers the node gRPC Query service.
		RegisterNodeService(client.Context, config.Config)

		/ CommitMultiStore return the multistore instance
		CommitMultiStore()

storetypes.CommitMultiStore

		/ Return the snapshot manager
		SnapshotManager() *snapshots.Manager

		/ Close is called in start cmd to gracefully cleanup resources.
		/ Must be safe to be called multiple times.
		Close()

error
}

	/ AppCreator is a function that allows us to lazily initialize an
	/ application using various configurations.
	AppCreator func(log.Logger, dbm.DB, io.Writer, AppOptions)

Application

	/ ModuleInitFlags takes a start command and adds modules specific init flags.
	ModuleInitFlags func(startCmd *cobra.Command)

	/ ExportedApp represents an exported app state, along with
	/ validators, consensus params and latest app height.
	ExportedApp struct {
		/ AppState is the application state as JSON.
		AppState json.RawMessage
		/ Validators is the exported validator set.
		Validators []cmttypes.GenesisValidator
		/ Height is the app's latest block height.
		Height int64
		/ ConsensusParams are the exported consensus params for ABCI.
		ConsensusParams cmtproto.ConsensusParams
}

	/ AppExporter is a function that dumps all app state to
	/ JSON-serializable structure and returns the current validator set.
	AppExporter func(
		logger log.Logger,
		db dbm.DB,
		traceWriter io.Writer,
		height int64,
    forZeroHeight bool,
		jailAllowedAddrs []string,
		opts AppOptions,
		modulesToExport []string,
	) (ExportedApp, error)
)
Here are the main actions performed by this function:
  • Instantiate a new codec and initialize the codec of each of the application’s modules using the basic manager.
  • Instantiate a new application with a reference to a baseapp instance, a codec, and all the appropriate store keys.
  • Instantiate all the keeper objects defined in the application’s type using the NewKeeper function of each of the application’s modules. Note that keepers must be instantiated in the correct order, as the NewKeeper of one module might require a reference to another module’s keeper.
  • Instantiate the application’s module manager with the AppModule object of each of the application’s modules.
  • With the module manager, initialize the application’s Msg services, gRPC Query services, legacy Msg routes, and legacy query routes. When a transaction is relayed to the application by CometBFT via the ABCI, it is routed to the appropriate module’s Msg service using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module’s gRPC query service using the gRPC routes defined here. The Cosmos SDK still supports legacy Msgs and legacy CometBFT queries, which are routed using the legacy Msg routes and the legacy query routes, respectively.
  • With the module manager, register the application’s modules’ invariants. Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the InvariantsRegistry. The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry is triggered (usually the chain is halted). This is useful to make sure that no critical bug goes unnoticed, producing long-lasting effects that are hard to fix.
  • With the module manager, set the order of execution between the InitGenesis, PreBlocker, BeginBlocker, and EndBlocker functions of each of the application’s modules. Note that not all modules implement these functions.
  • Set the remaining application parameters:
  • Mount the stores.
  • Return the application.
Note that the constructor function only creates an instance of the app, while the actual state is either carried over from the ~/.app/data folder if the node is restarted, or generated from the genesis file if the node is started for the first time. See an example of application constructor from simapp:
/go:build app_v1

package simapp

import (

	"encoding/json"
    "fmt"
    "io"
    "maps"

	abci "github.com/cometbft/cometbft/abci/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/cosmos/gogoproto/proto"
    "github.com/spf13/cast"

	autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
	reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
    "cosmossdk.io/client/v2/autocli"
	clienthelpers "cosmossdk.io/client/v2/helpers"
    "cosmossdk.io/core/appmodule"
    "cosmossdk.io/log"
	storetypes "cosmossdk.io/store/types"
    "cosmossdk.io/x/circuit"
	circuitkeeper "cosmossdk.io/x/circuit/keeper"
	circuittypes "cosmossdk.io/x/circuit/types"
    "cosmossdk.io/x/evidence"
	evidencekeeper "cosmossdk.io/x/evidence/keeper"
	evidencetypes "cosmossdk.io/x/evidence/types"
    "cosmossdk.io/x/feegrant"
	feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
	feegrantmodule "cosmossdk.io/x/feegrant/module"
    "cosmossdk.io/x/nft"
	nftkeeper "cosmossdk.io/x/nft/keeper"
	nftmodule "cosmossdk.io/x/nft/module"
    "cosmossdk.io/x/tx/signing"
    "cosmossdk.io/x/upgrade"
	upgradekeeper "cosmossdk.io/x/upgrade/keeper"
	upgradetypes "cosmossdk.io/x/upgrade/types"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
	nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/address"
    "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/runtime"
	runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
    "github.com/cosmos/cosmos-sdk/server"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    "github.com/cosmos/cosmos-sdk/std"
	testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
    "github.com/cosmos/cosmos-sdk/version"
    "github.com/cosmos/cosmos-sdk/x/auth"
    "github.com/cosmos/cosmos-sdk/x/auth/ante"
	authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
    "github.com/cosmos/cosmos-sdk/x/auth/posthandler"
	authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
    "github.com/cosmos/cosmos-sdk/x/auth/tx"
	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
	txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/auth/vesting"
	vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
    "github.com/cosmos/cosmos-sdk/x/authz"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
	authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
    "github.com/cosmos/cosmos-sdk/x/bank"
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
	consensus "github.com/cosmos/cosmos-sdk/x/consensus"
	consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
	consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
	distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
	distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
    "github.com/cosmos/cosmos-sdk/x/epochs"
	epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
	epochstypes "github.com/cosmos/cosmos-sdk/x/epochs/types"
    "github.com/cosmos/cosmos-sdk/x/genutil"
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
    "github.com/cosmos/cosmos-sdk/x/gov"
	govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
	govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    "github.com/cosmos/cosmos-sdk/x/group"
	groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
	groupmodule "github.com/cosmos/cosmos-sdk/x/group/module"
    "github.com/cosmos/cosmos-sdk/x/mint"
	mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    "github.com/cosmos/cosmos-sdk/x/protocolpool"
	protocolpoolkeeper "github.com/cosmos/cosmos-sdk/x/protocolpool/keeper"
	protocolpooltypes "github.com/cosmos/cosmos-sdk/x/protocolpool/types"
    "github.com/cosmos/cosmos-sdk/x/slashing"
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
	slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
    "github.com/cosmos/cosmos-sdk/x/staking"
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

const appName = "SimApp"

var (
	/ DefaultNodeHome default home directories for the application daemon
	DefaultNodeHome string

	/ module account permissions
	maccPerms = map[string][]string{
    authtypes.FeeCollectorName:                  nil,
		distrtypes.ModuleName:                       nil,
		minttypes.ModuleName:                        {
    authtypes.Minter
},
		stakingtypes.BondedPoolName:                 {
    authtypes.Burner, authtypes.Staking
},
		stakingtypes.NotBondedPoolName:              {
    authtypes.Burner, authtypes.Staking
},
		govtypes.ModuleName:                         {
    authtypes.Burner
},
		nft.ModuleName:                              nil,
		protocolpooltypes.ModuleName:                nil,
		protocolpooltypes.ProtocolPoolEscrowAccount: nil
}
)

var (
	_ runtime.AppI            = (*SimApp)(nil)
	_ servertypes.Application = (*SimApp)(nil)
)

/ SimApp extends an ABCI application, but with most of its parameters exported.
/ They are exported for convenience in creating helper functions, as object
/ capabilities aren't needed for testing.
type SimApp struct {
	*baseapp.BaseApp
	legacyAmino       *codec.LegacyAmino
	appCodec          codec.Codec
	txConfig          client.TxConfig
	interfaceRegistry types.InterfaceRegistry

	/ keys to access the substores
	keys map[string]*storetypes.KVStoreKey

	/ essential keepers
	AccountKeeper         authkeeper.AccountKeeper
	BankKeeper            bankkeeper.BaseKeeper
	StakingKeeper         *stakingkeeper.Keeper
	SlashingKeeper        slashingkeeper.Keeper
	MintKeeper            mintkeeper.Keeper
	DistrKeeper           distrkeeper.Keeper
	GovKeeper             govkeeper.Keeper
	UpgradeKeeper         *upgradekeeper.Keeper
	EvidenceKeeper        evidencekeeper.Keeper
	ConsensusParamsKeeper consensusparamkeeper.Keeper
	CircuitKeeper         circuitkeeper.Keeper

	/ supplementary keepers
	FeeGrantKeeper     feegrantkeeper.Keeper
	GroupKeeper        groupkeeper.Keeper
	AuthzKeeper        authzkeeper.Keeper
	NFTKeeper          nftkeeper.Keeper
	EpochsKeeper       epochskeeper.Keeper
	ProtocolPoolKeeper protocolpoolkeeper.Keeper

	/ the module manager
	ModuleManager      *module.Manager
	BasicModuleManager module.BasicManager

	/ simulation manager
	sm *module.SimulationManager

	/ module configurator
	configurator module.Configurator
}

func init() {
    var err error
	DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
    if err != nil {
    panic(err)
}
}

/ NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
	baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    interfaceRegistry, _ := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
    ProtoFiles: proto.HybridResolver,
    SigningOptions: signing.Options{
    AddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
    ValidatorAddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
},
})
    appCodec := codec.NewProtoCodec(interfaceRegistry)
    legacyAmino := codec.NewLegacyAmino()
    txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes)
    if err := interfaceRegistry.SigningContext().Validate(); err != nil {
    panic(err)
}

std.RegisterLegacyAminoCodec(legacyAmino)

std.RegisterInterfaces(interfaceRegistry)

	/ Below we could construct and set an application specific mempool and
	/ ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
	/ already set in the SDK's BaseApp, this shows an example of how to override
	/ them.
	/
	/ Example:
	/
	/ bApp := baseapp.NewBaseApp(...)
	/ nonceMempool := mempool.NewSenderNonceMempool()
	/ abciPropHandler := NewDefaultProposalHandler(nonceMempool, bApp)
	/
	/ bApp.SetMempool(nonceMempool)
	/ bApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/ bApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
	/
	/ Alternatively, you can construct BaseApp options, append those to
	/ baseAppOptions and pass them to NewBaseApp.
	/
	/ Example:
	/
	/ prepareOpt = func(app *baseapp.BaseApp) {
	/ 	abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
	/ 	app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/
}
	/ baseAppOptions = append(baseAppOptions, prepareOpt)

	/ create and set dummy vote extension handler
    voteExtOp := func(bApp *baseapp.BaseApp) {
    voteExtHandler := NewVoteExtensionHandler()

voteExtHandler.SetHandlers(bApp)
}

baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())
    bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)

bApp.SetCommitMultiStoreTracer(traceStore)

bApp.SetVersion(version.Version)

bApp.SetInterfaceRegistry(interfaceRegistry)

bApp.SetTxEncoder(txConfig.TxEncoder())
    keys := storetypes.NewKVStoreKeys(
		authtypes.StoreKey,
		banktypes.StoreKey,
		stakingtypes.StoreKey,
		minttypes.StoreKey,
		distrtypes.StoreKey,
		slashingtypes.StoreKey,
		govtypes.StoreKey,
		consensusparamtypes.StoreKey,
		upgradetypes.StoreKey,
		feegrant.StoreKey,
		evidencetypes.StoreKey,
		circuittypes.StoreKey,
		authzkeeper.StoreKey,
		nftkeeper.StoreKey,
		group.StoreKey,
		epochstypes.StoreKey,
		protocolpooltypes.StoreKey,
	)

	/ register streaming services
    if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
    panic(err)
}
    app := &SimApp{
    BaseApp:           bApp,
		legacyAmino:       legacyAmino,
		appCodec:          appCodec,
		txConfig:          txConfig,
		interfaceRegistry: interfaceRegistry,
		keys:              keys,
}

	/ set the BaseApp's parameter store
	app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		runtime.EventService{
},
	)

bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore)

	/ add keepers
	app.AccountKeeper = authkeeper.NewAccountKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[authtypes.StoreKey]),
		authtypes.ProtoBaseAccount,
		maccPerms,
		authcodec.NewBech32Codec(sdk.Bech32MainPrefix),
		sdk.Bech32MainPrefix,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authkeeper.WithUnorderedTransactions(true),
	)

app.BankKeeper = bankkeeper.NewBaseKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[banktypes.StoreKey]),
		app.AccountKeeper,
		BlockedAddresses(),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		logger,
	)

	/ optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper)
    enabledSignModes := append(tx.DefaultSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL)
    txConfigOpts := tx.ConfigOptions{
    EnabledSignModes:           enabledSignModes,
    TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper),
}

txConfig, err := tx.NewTxConfigWithOptions(
		appCodec,
		txConfigOpts,
	)
    if err != nil {
    panic(err)
}

app.txConfig = txConfig

	app.StakingKeeper = stakingkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authcodec.NewBech32Codec(sdk.Bech32PrefixValAddr),
		authcodec.NewBech32Codec(sdk.Bech32PrefixConsAddr),
	)

app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ mintkeeper.WithMintFn(mintkeeper.DefaultMintFn(minttypes.DefaultInflationCalculationFn)), custom mintFn can be added here
	)

app.ProtocolPoolKeeper = protocolpoolkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[protocolpooltypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.DistrKeeper = distrkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[distrtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		distrkeeper.WithExternalCommunityPool(app.ProtocolPoolKeeper),
	)

app.SlashingKeeper = slashingkeeper.NewKeeper(
		appCodec,
		legacyAmino,
		runtime.NewKVStoreService(keys[slashingtypes.StoreKey]),
		app.StakingKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[feegrant.StoreKey]),
		app.AccountKeeper,
	)

	/ register the staking hooks
	/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
	app.StakingKeeper.SetHooks(
		stakingtypes.NewMultiStakingHooks(
			app.DistrKeeper.Hooks(),
			app.SlashingKeeper.Hooks(),
		),
	)

app.CircuitKeeper = circuitkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[circuittypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		app.AccountKeeper.AddressCodec(),
	)

app.BaseApp.SetCircuitBreaker(&app.CircuitKeeper)

app.AuthzKeeper = authzkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[authzkeeper.StoreKey]),
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
	)
    groupConfig := group.DefaultConfig()
	/*
		Example of setting group params:
		groupConfig.MaxMetadataLen = 1000
	*/
	app.GroupKeeper = groupkeeper.NewKeeper(
		keys[group.StoreKey],
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
		groupConfig,
	)

	/ get skipUpgradeHeights from the app options
    skipUpgradeHeights := map[int64]bool{
}
    for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
    skipUpgradeHeights[int64(h)] = true
}
    homePath := cast.ToString(appOpts.Get(flags.FlagHome))
	/ set the governance module account as the authority for conducting upgrades
	app.UpgradeKeeper = upgradekeeper.NewKeeper(
		skipUpgradeHeights,
		runtime.NewKVStoreService(keys[upgradetypes.StoreKey]),
		appCodec,
		homePath,
		app.BaseApp,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

	/ Register the proposal types
	/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
	/ by granting the governance module the right to execute the message.
	/ See: https://docs.cosmos.network/main/modules/gov#proposal-messages
    govRouter := govv1beta1.NewRouter()

govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler)
    govConfig := govtypes.DefaultConfig()
	/*
		Example of setting gov params:
		govConfig.MaxMetadataLen = 10000
	*/
    govKeeper := govkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[govtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		app.DistrKeeper,
		app.MsgServiceRouter(),
		govConfig,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ govkeeper.WithCustomCalculateVoteResultsAndVotingPowerFn(...), / Add if you want to use a custom vote calculation function.
	)

	/ Set legacy router for backwards compatibility with gov v1beta1
	govKeeper.SetLegacyRouter(govRouter)

app.GovKeeper = *govKeeper.SetHooks(
		govtypes.NewMultiGovHooks(
			/ register the governance hooks
		),
	)

app.NFTKeeper = nftkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[nftkeeper.StoreKey]),
		appCodec,
		app.AccountKeeper,
		app.BankKeeper,
	)

	/ create evidence keeper with router
    evidenceKeeper := evidencekeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[evidencetypes.StoreKey]),
		app.StakingKeeper,
		app.SlashingKeeper,
		app.AccountKeeper.AddressCodec(),
		runtime.ProvideCometInfoService(),
	)
	/ If evidence needs to be handled for the app, set routes in router here and seal
	app.EvidenceKeeper = *evidenceKeeper

	app.EpochsKeeper = epochskeeper.NewKeeper(
		runtime.NewKVStoreService(keys[epochstypes.StoreKey]),
		appCodec,
	)

app.EpochsKeeper.SetHooks(
		epochstypes.NewMultiEpochHooks(
			/ insert epoch hooks receivers here
		),
	)

	/****  Module Options ****/

	/ NOTE: Any module instantiated in the module manager that is later modified
	/ must be passed by reference here.
	app.ModuleManager = module.NewManager(
		genutil.NewAppModule(
			app.AccountKeeper, app.StakingKeeper, app,
			txConfig,
		),
		auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
		vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
		bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
		feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
		gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
		mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil),
		slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry),
		distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
		staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil),
		upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()),
		evidence.NewAppModule(app.EvidenceKeeper),
		authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
		circuit.NewAppModule(appCodec, app.CircuitKeeper),
		epochs.NewAppModule(app.EpochsKeeper),
		protocolpool.NewAppModule(app.ProtocolPoolKeeper, app.AccountKeeper, app.BankKeeper),
	)

	/ BasicModuleManager defines the module BasicManager is in charge of setting up basic,
	/ non-dependant module elements, such as codec registration and genesis verification.
	/ By default it is composed of all the module from the module manager.
	/ Additionally, app module basics can be overwritten by passing them as argument.
	app.BasicModuleManager = module.NewBasicManagerFromManager(
		app.ModuleManager,
		map[string]module.AppModuleBasic{
    genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
			govtypes.ModuleName: gov.NewAppModuleBasic(
				[]govclient.ProposalHandler{
},
			),
})

app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)

app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)

	/ NOTE: upgrade module is required to be prioritized
	app.ModuleManager.SetOrderPreBlockers(
		upgradetypes.ModuleName,
		authtypes.ModuleName,
	)
	/ During begin block slashing happens after distr.BeginBlocker so that
	/ there is nothing left over in the validator fee pool, so as to keep the
	/ CanWithdrawInvariant invariant.
	/ NOTE: staking module is required if HistoricalEntries param > 0
	app.ModuleManager.SetOrderBeginBlockers(
		minttypes.ModuleName,
		distrtypes.ModuleName,
		protocolpooltypes.ModuleName,
		slashingtypes.ModuleName,
		evidencetypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		authz.ModuleName,
		epochstypes.ModuleName,
	)

app.ModuleManager.SetOrderEndBlockers(
		govtypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		feegrant.ModuleName,
		group.ModuleName,
		protocolpooltypes.ModuleName,
	)

	/ NOTE: The genutils module must occur after staking so that pools are
	/ properly initialized with tokens from genesis accounts.
	/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
    genesisModuleOrder := []string{
    authtypes.ModuleName,
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		consensusparamtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
		protocolpooltypes.ModuleName,
}
    exportModuleOrder := []string{
    consensusparamtypes.ModuleName,
		authtypes.ModuleName,
		protocolpooltypes.ModuleName, / Must be exported before bank
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
}

app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)

app.ModuleManager.SetOrderExportGenesis(exportModuleOrder...)

	/ Uncomment if you want to set a custom migration order here.
	/ app.ModuleManager.SetOrderMigrations(custom order)

app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())

err = app.ModuleManager.RegisterServices(app.configurator)
    if err != nil {
    panic(err)
}

	/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
	/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
	app.RegisterUpgradeHandlers()

autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))

reflectionSvc, err := runtimeservices.NewReflectionService()
    if err != nil {
    panic(err)
}

reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)

	/ add test gRPC service for testing gRPC queries in isolation
	testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{
})

	/ create the simulation manager and define the order of the modules for deterministic simulations
	/
	/ NOTE: this is not required apps that don't use the simulator for fuzz testing
	/ transactions
    overrideModules := map[string]module.AppModuleSimulation{
    authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}

app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

	/ initialize stores
	app.MountKVStores(keys)

	/ initialize BaseApp
	app.SetInitChainer(app.InitChainer)

app.SetPreBlocker(app.PreBlocker)

app.SetBeginBlocker(app.BeginBlocker)

app.SetEndBlocker(app.EndBlocker)

app.setAnteHandler(txConfig)

	/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
	/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
	/ defined as a chain, and have the same signature as antehandlers.
	/
	/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
	/ meaning that both `runMsgs` and `postHandler` state will be committed if
	/ both are successful, and both will be reverted if any of the two fails.
	/
	/ The SDK exposes a default postHandlers chain
	/
	/ Please note that changing any of the anteHandler or postHandler chain is
	/ likely to be a state-machine breaking change, which needs a coordinated
	/ upgrade.
	app.setPostHandler()
    if loadLatest {
    if err := app.LoadLatestVersion(); err != nil {
    panic(fmt.Errorf("error loading last version: %w", err))
}

}

return app
}

func (app *SimApp)

setAnteHandler(txConfig client.TxConfig) {
    anteHandler, err := NewAnteHandler(
		HandlerOptions{
    ante.HandlerOptions{
    AccountKeeper:   app.AccountKeeper,
    BankKeeper:      app.BankKeeper,
    SignModeHandler: txConfig.SignModeHandler(),
    FeegrantKeeper:  app.FeeGrantKeeper,
    SigGasConsumer:  ante.DefaultSigVerificationGasConsumer,
    SigVerifyOptions: []ante.SigVerificationDecoratorOption{
					/ change below as needed.
					ante.WithUnorderedTxGasCost(ante.DefaultUnorderedTxGasCost),
					ante.WithMaxUnorderedTxTimeoutDuration(ante.DefaultMaxTimeoutDuration),
},
},
			&app.CircuitKeeper,
},
	)
    if err != nil {
    panic(err)
}

	/ Set the AnteHandler for the app
	app.SetAnteHandler(anteHandler)
}

func (app *SimApp)

setPostHandler() {
    postHandler, err := posthandler.NewPostHandler(
		posthandler.HandlerOptions{
},
	)
    if err != nil {
    panic(err)
}

app.SetPostHandler(postHandler)
}

/ Name returns the name of the App
func (app *SimApp)

Name()

string {
    return app.BaseApp.Name()
}

/ PreBlocker application updates every pre block
func (app *SimApp)

PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
    return app.ModuleManager.PreBlock(ctx)
}

/ BeginBlocker application updates every begin block
func (app *SimApp)

BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
    return app.ModuleManager.BeginBlock(ctx)
}

/ EndBlocker application updates every end block
func (app *SimApp)

EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
    return app.ModuleManager.EndBlock(ctx)
}

func (a *SimApp)

Configurator()

module.Configurator {
    return a.configurator
}

/ InitChainer application update at chain initialization
func (app *SimApp)

InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
    var genesisState GenesisState
    if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
    panic(err)
}

app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())

return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}

/ LoadHeight loads a particular height
func (app *SimApp)

LoadHeight(height int64)

error {
    return app.LoadVersion(height)
}

/ LegacyAmino returns SimApp's amino codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

LegacyAmino() *codec.LegacyAmino {
    return app.legacyAmino
}

/ AppCodec returns SimApp's app codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

AppCodec()

codec.Codec {
    return app.appCodec
}

/ InterfaceRegistry returns SimApp's InterfaceRegistry
func (app *SimApp)

InterfaceRegistry()

types.InterfaceRegistry {
    return app.interfaceRegistry
}

/ TxConfig returns SimApp's TxConfig
func (app *SimApp)

TxConfig()

client.TxConfig {
    return app.txConfig
}

/ AutoCliOpts returns the autocli options for the app.
func (app *SimApp)

AutoCliOpts()

autocli.AppOptions {
    modules := make(map[string]appmodule.AppModule, 0)
    for _, m := range app.ModuleManager.Modules {
    if moduleWithName, ok := m.(module.HasName); ok {
    moduleName := moduleWithName.Name()
    if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
    modules[moduleName] = appModule
}

}

}

return autocli.AppOptions{
    Modules:               modules,
    ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
    AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
    ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
    ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)

DefaultGenesis()

map[string]json.RawMessage {
    return a.BasicModuleManager.DefaultGenesis(a.appCodec)
}

/ GetKey returns the KVStoreKey for the provided store key.
/
/ NOTE: This is solely to be used for testing purposes.
func (app *SimApp)

GetKey(storeKey string) *storetypes.KVStoreKey {
    return app.keys[storeKey]
}

/ GetStoreKeys returns all the stored store keys.
func (app *SimApp)

GetStoreKeys() []storetypes.StoreKey {
    keys := make([]storetypes.StoreKey, 0, len(app.keys))
    for _, key := range app.keys {
    keys = append(keys, key)
}

return keys
}

/ SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}

/ RegisterAPIRoutes registers all application module routes with the provided
/ API server.
func (app *SimApp)

RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    clientCtx := apiSvr.ClientCtx
	/ Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ register swagger API from root so that other applications can override easily
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
}
}

/ RegisterTxService implements the Application.RegisterTxService method.
func (app *SimApp)

RegisterTxService(clientCtx client.Context) {
    authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}

/ RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *SimApp)

RegisterTendermintService(clientCtx client.Context) {
    cmtApp := server.NewCometABCIWrapper(app)

cmtservice.RegisterTendermintService(
		clientCtx,
		app.BaseApp.GRPCQueryRouter(),
		app.interfaceRegistry,
		cmtApp.Query,
	)
}

func (app *SimApp)

RegisterNodeService(clientCtx client.Context, cfg config.Config) {
    nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg)
}

/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()

map[string][]string {
    return maps.Clone(maccPerms)
}

/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()

map[string]bool {
    modAccAddrs := make(map[string]bool)
    for acc := range GetMaccPerms() {
    modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}

	/ allow the following addresses to receive funds
	delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())

return modAccAddrs
}

InitChainer

The InitChainer is a function that initializes the state of the application from a genesis file (i.e. token balances of genesis accounts). It is called when the application receives the InitChain message from the CometBFT engine, which happens when the node is started at appBlockHeight == 0 (i.e. on genesis). The application must set the InitChainer in its constructor via the SetInitChainer method. In general, the InitChainer is mostly composed of the InitGenesis function of each of the application’s modules. This is done by calling the InitGenesis function of the module manager, which in turn calls the InitGenesis function of each of the modules it contains. Note that the order in which the modules’ InitGenesis functions must be called has to be set in the module manager using the module manager’s SetOrderInitGenesis method. This is done in the application’s constructor, and the SetOrderInitGenesis has to be called before the SetInitChainer. See an example of an InitChainer from simapp:
/go:build app_v1

package simapp

import (

	"encoding/json"
    "fmt"
    "io"
    "maps"

	abci "github.com/cometbft/cometbft/abci/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/cosmos/gogoproto/proto"
    "github.com/spf13/cast"

	autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
	reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
    "cosmossdk.io/client/v2/autocli"
	clienthelpers "cosmossdk.io/client/v2/helpers"
    "cosmossdk.io/core/appmodule"
    "cosmossdk.io/log"
	storetypes "cosmossdk.io/store/types"
    "cosmossdk.io/x/circuit"
	circuitkeeper "cosmossdk.io/x/circuit/keeper"
	circuittypes "cosmossdk.io/x/circuit/types"
    "cosmossdk.io/x/evidence"
	evidencekeeper "cosmossdk.io/x/evidence/keeper"
	evidencetypes "cosmossdk.io/x/evidence/types"
    "cosmossdk.io/x/feegrant"
	feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
	feegrantmodule "cosmossdk.io/x/feegrant/module"
    "cosmossdk.io/x/nft"
	nftkeeper "cosmossdk.io/x/nft/keeper"
	nftmodule "cosmossdk.io/x/nft/module"
    "cosmossdk.io/x/tx/signing"
    "cosmossdk.io/x/upgrade"
	upgradekeeper "cosmossdk.io/x/upgrade/keeper"
	upgradetypes "cosmossdk.io/x/upgrade/types"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
	nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/address"
    "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/runtime"
	runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
    "github.com/cosmos/cosmos-sdk/server"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    "github.com/cosmos/cosmos-sdk/std"
	testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
    "github.com/cosmos/cosmos-sdk/version"
    "github.com/cosmos/cosmos-sdk/x/auth"
    "github.com/cosmos/cosmos-sdk/x/auth/ante"
	authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
    "github.com/cosmos/cosmos-sdk/x/auth/posthandler"
	authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
    "github.com/cosmos/cosmos-sdk/x/auth/tx"
	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
	txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/auth/vesting"
	vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
    "github.com/cosmos/cosmos-sdk/x/authz"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
	authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
    "github.com/cosmos/cosmos-sdk/x/bank"
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
	consensus "github.com/cosmos/cosmos-sdk/x/consensus"
	consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
	consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
	distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
	distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
    "github.com/cosmos/cosmos-sdk/x/epochs"
	epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
	epochstypes "github.com/cosmos/cosmos-sdk/x/epochs/types"
    "github.com/cosmos/cosmos-sdk/x/genutil"
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
    "github.com/cosmos/cosmos-sdk/x/gov"
	govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
	govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    "github.com/cosmos/cosmos-sdk/x/group"
	groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
	groupmodule "github.com/cosmos/cosmos-sdk/x/group/module"
    "github.com/cosmos/cosmos-sdk/x/mint"
	mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    "github.com/cosmos/cosmos-sdk/x/protocolpool"
	protocolpoolkeeper "github.com/cosmos/cosmos-sdk/x/protocolpool/keeper"
	protocolpooltypes "github.com/cosmos/cosmos-sdk/x/protocolpool/types"
    "github.com/cosmos/cosmos-sdk/x/slashing"
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
	slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
    "github.com/cosmos/cosmos-sdk/x/staking"
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

const appName = "SimApp"

var (
	/ DefaultNodeHome default home directories for the application daemon
	DefaultNodeHome string

	/ module account permissions
	maccPerms = map[string][]string{
    authtypes.FeeCollectorName:                  nil,
		distrtypes.ModuleName:                       nil,
		minttypes.ModuleName:                        {
    authtypes.Minter
},
		stakingtypes.BondedPoolName:                 {
    authtypes.Burner, authtypes.Staking
},
		stakingtypes.NotBondedPoolName:              {
    authtypes.Burner, authtypes.Staking
},
		govtypes.ModuleName:                         {
    authtypes.Burner
},
		nft.ModuleName:                              nil,
		protocolpooltypes.ModuleName:                nil,
		protocolpooltypes.ProtocolPoolEscrowAccount: nil
}
)

var (
	_ runtime.AppI            = (*SimApp)(nil)
	_ servertypes.Application = (*SimApp)(nil)
)

/ SimApp extends an ABCI application, but with most of its parameters exported.
/ They are exported for convenience in creating helper functions, as object
/ capabilities aren't needed for testing.
type SimApp struct {
	*baseapp.BaseApp
	legacyAmino       *codec.LegacyAmino
	appCodec          codec.Codec
	txConfig          client.TxConfig
	interfaceRegistry types.InterfaceRegistry

	/ keys to access the substores
	keys map[string]*storetypes.KVStoreKey

	/ essential keepers
	AccountKeeper         authkeeper.AccountKeeper
	BankKeeper            bankkeeper.BaseKeeper
	StakingKeeper         *stakingkeeper.Keeper
	SlashingKeeper        slashingkeeper.Keeper
	MintKeeper            mintkeeper.Keeper
	DistrKeeper           distrkeeper.Keeper
	GovKeeper             govkeeper.Keeper
	UpgradeKeeper         *upgradekeeper.Keeper
	EvidenceKeeper        evidencekeeper.Keeper
	ConsensusParamsKeeper consensusparamkeeper.Keeper
	CircuitKeeper         circuitkeeper.Keeper

	/ supplementary keepers
	FeeGrantKeeper     feegrantkeeper.Keeper
	GroupKeeper        groupkeeper.Keeper
	AuthzKeeper        authzkeeper.Keeper
	NFTKeeper          nftkeeper.Keeper
	EpochsKeeper       epochskeeper.Keeper
	ProtocolPoolKeeper protocolpoolkeeper.Keeper

	/ the module manager
	ModuleManager      *module.Manager
	BasicModuleManager module.BasicManager

	/ simulation manager
	sm *module.SimulationManager

	/ module configurator
	configurator module.Configurator
}

func init() {
    var err error
	DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
    if err != nil {
    panic(err)
}
}

/ NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
	baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    interfaceRegistry, _ := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
    ProtoFiles: proto.HybridResolver,
    SigningOptions: signing.Options{
    AddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
    ValidatorAddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
},
})
    appCodec := codec.NewProtoCodec(interfaceRegistry)
    legacyAmino := codec.NewLegacyAmino()
    txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes)
    if err := interfaceRegistry.SigningContext().Validate(); err != nil {
    panic(err)
}

std.RegisterLegacyAminoCodec(legacyAmino)

std.RegisterInterfaces(interfaceRegistry)

	/ Below we could construct and set an application specific mempool and
	/ ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
	/ already set in the SDK's BaseApp, this shows an example of how to override
	/ them.
	/
	/ Example:
	/
	/ bApp := baseapp.NewBaseApp(...)
	/ nonceMempool := mempool.NewSenderNonceMempool()
	/ abciPropHandler := NewDefaultProposalHandler(nonceMempool, bApp)
	/
	/ bApp.SetMempool(nonceMempool)
	/ bApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/ bApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
	/
	/ Alternatively, you can construct BaseApp options, append those to
	/ baseAppOptions and pass them to NewBaseApp.
	/
	/ Example:
	/
	/ prepareOpt = func(app *baseapp.BaseApp) {
	/ 	abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
	/ 	app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/
}
	/ baseAppOptions = append(baseAppOptions, prepareOpt)

	/ create and set dummy vote extension handler
    voteExtOp := func(bApp *baseapp.BaseApp) {
    voteExtHandler := NewVoteExtensionHandler()

voteExtHandler.SetHandlers(bApp)
}

baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())
    bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)

bApp.SetCommitMultiStoreTracer(traceStore)

bApp.SetVersion(version.Version)

bApp.SetInterfaceRegistry(interfaceRegistry)

bApp.SetTxEncoder(txConfig.TxEncoder())
    keys := storetypes.NewKVStoreKeys(
		authtypes.StoreKey,
		banktypes.StoreKey,
		stakingtypes.StoreKey,
		minttypes.StoreKey,
		distrtypes.StoreKey,
		slashingtypes.StoreKey,
		govtypes.StoreKey,
		consensusparamtypes.StoreKey,
		upgradetypes.StoreKey,
		feegrant.StoreKey,
		evidencetypes.StoreKey,
		circuittypes.StoreKey,
		authzkeeper.StoreKey,
		nftkeeper.StoreKey,
		group.StoreKey,
		epochstypes.StoreKey,
		protocolpooltypes.StoreKey,
	)

	/ register streaming services
    if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
    panic(err)
}
    app := &SimApp{
    BaseApp:           bApp,
		legacyAmino:       legacyAmino,
		appCodec:          appCodec,
		txConfig:          txConfig,
		interfaceRegistry: interfaceRegistry,
		keys:              keys,
}

	/ set the BaseApp's parameter store
	app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		runtime.EventService{
},
	)

bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore)

	/ add keepers
	app.AccountKeeper = authkeeper.NewAccountKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[authtypes.StoreKey]),
		authtypes.ProtoBaseAccount,
		maccPerms,
		authcodec.NewBech32Codec(sdk.Bech32MainPrefix),
		sdk.Bech32MainPrefix,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authkeeper.WithUnorderedTransactions(true),
	)

app.BankKeeper = bankkeeper.NewBaseKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[banktypes.StoreKey]),
		app.AccountKeeper,
		BlockedAddresses(),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		logger,
	)

	/ optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper)
    enabledSignModes := append(tx.DefaultSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL)
    txConfigOpts := tx.ConfigOptions{
    EnabledSignModes:           enabledSignModes,
    TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper),
}

txConfig, err := tx.NewTxConfigWithOptions(
		appCodec,
		txConfigOpts,
	)
    if err != nil {
    panic(err)
}

app.txConfig = txConfig

	app.StakingKeeper = stakingkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authcodec.NewBech32Codec(sdk.Bech32PrefixValAddr),
		authcodec.NewBech32Codec(sdk.Bech32PrefixConsAddr),
	)

app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ mintkeeper.WithMintFn(mintkeeper.DefaultMintFn(minttypes.DefaultInflationCalculationFn)), custom mintFn can be added here
	)

app.ProtocolPoolKeeper = protocolpoolkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[protocolpooltypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.DistrKeeper = distrkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[distrtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		distrkeeper.WithExternalCommunityPool(app.ProtocolPoolKeeper),
	)

app.SlashingKeeper = slashingkeeper.NewKeeper(
		appCodec,
		legacyAmino,
		runtime.NewKVStoreService(keys[slashingtypes.StoreKey]),
		app.StakingKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[feegrant.StoreKey]),
		app.AccountKeeper,
	)

	/ register the staking hooks
	/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
	app.StakingKeeper.SetHooks(
		stakingtypes.NewMultiStakingHooks(
			app.DistrKeeper.Hooks(),
			app.SlashingKeeper.Hooks(),
		),
	)

app.CircuitKeeper = circuitkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[circuittypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		app.AccountKeeper.AddressCodec(),
	)

app.BaseApp.SetCircuitBreaker(&app.CircuitKeeper)

app.AuthzKeeper = authzkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[authzkeeper.StoreKey]),
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
	)
    groupConfig := group.DefaultConfig()
	/*
		Example of setting group params:
		groupConfig.MaxMetadataLen = 1000
	*/
	app.GroupKeeper = groupkeeper.NewKeeper(
		keys[group.StoreKey],
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
		groupConfig,
	)

	/ get skipUpgradeHeights from the app options
    skipUpgradeHeights := map[int64]bool{
}
    for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
    skipUpgradeHeights[int64(h)] = true
}
    homePath := cast.ToString(appOpts.Get(flags.FlagHome))
	/ set the governance module account as the authority for conducting upgrades
	app.UpgradeKeeper = upgradekeeper.NewKeeper(
		skipUpgradeHeights,
		runtime.NewKVStoreService(keys[upgradetypes.StoreKey]),
		appCodec,
		homePath,
		app.BaseApp,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

	/ Register the proposal types
	/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
	/ by granting the governance module the right to execute the message.
	/ See: https://docs.cosmos.network/main/modules/gov#proposal-messages
    govRouter := govv1beta1.NewRouter()

govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler)
    govConfig := govtypes.DefaultConfig()
	/*
		Example of setting gov params:
		govConfig.MaxMetadataLen = 10000
	*/
    govKeeper := govkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[govtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		app.DistrKeeper,
		app.MsgServiceRouter(),
		govConfig,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ govkeeper.WithCustomCalculateVoteResultsAndVotingPowerFn(...), / Add if you want to use a custom vote calculation function.
	)

	/ Set legacy router for backwards compatibility with gov v1beta1
	govKeeper.SetLegacyRouter(govRouter)

app.GovKeeper = *govKeeper.SetHooks(
		govtypes.NewMultiGovHooks(
			/ register the governance hooks
		),
	)

app.NFTKeeper = nftkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[nftkeeper.StoreKey]),
		appCodec,
		app.AccountKeeper,
		app.BankKeeper,
	)

	/ create evidence keeper with router
    evidenceKeeper := evidencekeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[evidencetypes.StoreKey]),
		app.StakingKeeper,
		app.SlashingKeeper,
		app.AccountKeeper.AddressCodec(),
		runtime.ProvideCometInfoService(),
	)
	/ If evidence needs to be handled for the app, set routes in router here and seal
	app.EvidenceKeeper = *evidenceKeeper

	app.EpochsKeeper = epochskeeper.NewKeeper(
		runtime.NewKVStoreService(keys[epochstypes.StoreKey]),
		appCodec,
	)

app.EpochsKeeper.SetHooks(
		epochstypes.NewMultiEpochHooks(
			/ insert epoch hooks receivers here
		),
	)

	/****  Module Options ****/

	/ NOTE: Any module instantiated in the module manager that is later modified
	/ must be passed by reference here.
	app.ModuleManager = module.NewManager(
		genutil.NewAppModule(
			app.AccountKeeper, app.StakingKeeper, app,
			txConfig,
		),
		auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
		vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
		bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
		feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
		gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
		mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil),
		slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry),
		distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
		staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil),
		upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()),
		evidence.NewAppModule(app.EvidenceKeeper),
		authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
		circuit.NewAppModule(appCodec, app.CircuitKeeper),
		epochs.NewAppModule(app.EpochsKeeper),
		protocolpool.NewAppModule(app.ProtocolPoolKeeper, app.AccountKeeper, app.BankKeeper),
	)

	/ BasicModuleManager defines the module BasicManager is in charge of setting up basic,
	/ non-dependant module elements, such as codec registration and genesis verification.
	/ By default it is composed of all the module from the module manager.
	/ Additionally, app module basics can be overwritten by passing them as argument.
	app.BasicModuleManager = module.NewBasicManagerFromManager(
		app.ModuleManager,
		map[string]module.AppModuleBasic{
    genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
			govtypes.ModuleName: gov.NewAppModuleBasic(
				[]govclient.ProposalHandler{
},
			),
})

app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)

app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)

	/ NOTE: upgrade module is required to be prioritized
	app.ModuleManager.SetOrderPreBlockers(
		upgradetypes.ModuleName,
		authtypes.ModuleName,
	)
	/ During begin block slashing happens after distr.BeginBlocker so that
	/ there is nothing left over in the validator fee pool, so as to keep the
	/ CanWithdrawInvariant invariant.
	/ NOTE: staking module is required if HistoricalEntries param > 0
	app.ModuleManager.SetOrderBeginBlockers(
		minttypes.ModuleName,
		distrtypes.ModuleName,
		protocolpooltypes.ModuleName,
		slashingtypes.ModuleName,
		evidencetypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		authz.ModuleName,
		epochstypes.ModuleName,
	)

app.ModuleManager.SetOrderEndBlockers(
		govtypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		feegrant.ModuleName,
		group.ModuleName,
		protocolpooltypes.ModuleName,
	)

	/ NOTE: The genutils module must occur after staking so that pools are
	/ properly initialized with tokens from genesis accounts.
	/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
    genesisModuleOrder := []string{
    authtypes.ModuleName,
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		consensusparamtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
		protocolpooltypes.ModuleName,
}
    exportModuleOrder := []string{
    consensusparamtypes.ModuleName,
		authtypes.ModuleName,
		protocolpooltypes.ModuleName, / Must be exported before bank
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
}

app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)

app.ModuleManager.SetOrderExportGenesis(exportModuleOrder...)

	/ Uncomment if you want to set a custom migration order here.
	/ app.ModuleManager.SetOrderMigrations(custom order)

app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())

err = app.ModuleManager.RegisterServices(app.configurator)
    if err != nil {
    panic(err)
}

	/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
	/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
	app.RegisterUpgradeHandlers()

autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))

reflectionSvc, err := runtimeservices.NewReflectionService()
    if err != nil {
    panic(err)
}

reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)

	/ add test gRPC service for testing gRPC queries in isolation
	testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{
})

	/ create the simulation manager and define the order of the modules for deterministic simulations
	/
	/ NOTE: this is not required apps that don't use the simulator for fuzz testing
	/ transactions
    overrideModules := map[string]module.AppModuleSimulation{
    authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}

app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

	/ initialize stores
	app.MountKVStores(keys)

	/ initialize BaseApp
	app.SetInitChainer(app.InitChainer)

app.SetPreBlocker(app.PreBlocker)

app.SetBeginBlocker(app.BeginBlocker)

app.SetEndBlocker(app.EndBlocker)

app.setAnteHandler(txConfig)

	/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
	/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
	/ defined as a chain, and have the same signature as antehandlers.
	/
	/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
	/ meaning that both `runMsgs` and `postHandler` state will be committed if
	/ both are successful, and both will be reverted if any of the two fails.
	/
	/ The SDK exposes a default postHandlers chain
	/
	/ Please note that changing any of the anteHandler or postHandler chain is
	/ likely to be a state-machine breaking change, which needs a coordinated
	/ upgrade.
	app.setPostHandler()
    if loadLatest {
    if err := app.LoadLatestVersion(); err != nil {
    panic(fmt.Errorf("error loading last version: %w", err))
}

}

return app
}

func (app *SimApp)

setAnteHandler(txConfig client.TxConfig) {
    anteHandler, err := NewAnteHandler(
		HandlerOptions{
    ante.HandlerOptions{
    AccountKeeper:   app.AccountKeeper,
    BankKeeper:      app.BankKeeper,
    SignModeHandler: txConfig.SignModeHandler(),
    FeegrantKeeper:  app.FeeGrantKeeper,
    SigGasConsumer:  ante.DefaultSigVerificationGasConsumer,
    SigVerifyOptions: []ante.SigVerificationDecoratorOption{
					/ change below as needed.
					ante.WithUnorderedTxGasCost(ante.DefaultUnorderedTxGasCost),
					ante.WithMaxUnorderedTxTimeoutDuration(ante.DefaultMaxTimeoutDuration),
},
},
			&app.CircuitKeeper,
},
	)
    if err != nil {
    panic(err)
}

	/ Set the AnteHandler for the app
	app.SetAnteHandler(anteHandler)
}

func (app *SimApp)

setPostHandler() {
    postHandler, err := posthandler.NewPostHandler(
		posthandler.HandlerOptions{
},
	)
    if err != nil {
    panic(err)
}

app.SetPostHandler(postHandler)
}

/ Name returns the name of the App
func (app *SimApp)

Name()

string {
    return app.BaseApp.Name()
}

/ PreBlocker application updates every pre block
func (app *SimApp)

PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
    return app.ModuleManager.PreBlock(ctx)
}

/ BeginBlocker application updates every begin block
func (app *SimApp)

BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
    return app.ModuleManager.BeginBlock(ctx)
}

/ EndBlocker application updates every end block
func (app *SimApp)

EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
    return app.ModuleManager.EndBlock(ctx)
}

func (a *SimApp)

Configurator()

module.Configurator {
    return a.configurator
}

/ InitChainer application update at chain initialization
func (app *SimApp)

InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
    var genesisState GenesisState
    if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
    panic(err)
}

app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())

return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}

/ LoadHeight loads a particular height
func (app *SimApp)

LoadHeight(height int64)

error {
    return app.LoadVersion(height)
}

/ LegacyAmino returns SimApp's amino codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

LegacyAmino() *codec.LegacyAmino {
    return app.legacyAmino
}

/ AppCodec returns SimApp's app codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

AppCodec()

codec.Codec {
    return app.appCodec
}

/ InterfaceRegistry returns SimApp's InterfaceRegistry
func (app *SimApp)

InterfaceRegistry()

types.InterfaceRegistry {
    return app.interfaceRegistry
}

/ TxConfig returns SimApp's TxConfig
func (app *SimApp)

TxConfig()

client.TxConfig {
    return app.txConfig
}

/ AutoCliOpts returns the autocli options for the app.
func (app *SimApp)

AutoCliOpts()

autocli.AppOptions {
    modules := make(map[string]appmodule.AppModule, 0)
    for _, m := range app.ModuleManager.Modules {
    if moduleWithName, ok := m.(module.HasName); ok {
    moduleName := moduleWithName.Name()
    if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
    modules[moduleName] = appModule
}

}

}

return autocli.AppOptions{
    Modules:               modules,
    ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
    AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
    ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
    ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)

DefaultGenesis()

map[string]json.RawMessage {
    return a.BasicModuleManager.DefaultGenesis(a.appCodec)
}

/ GetKey returns the KVStoreKey for the provided store key.
/
/ NOTE: This is solely to be used for testing purposes.
func (app *SimApp)

GetKey(storeKey string) *storetypes.KVStoreKey {
    return app.keys[storeKey]
}

/ GetStoreKeys returns all the stored store keys.
func (app *SimApp)

GetStoreKeys() []storetypes.StoreKey {
    keys := make([]storetypes.StoreKey, 0, len(app.keys))
    for _, key := range app.keys {
    keys = append(keys, key)
}

return keys
}

/ SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}

/ RegisterAPIRoutes registers all application module routes with the provided
/ API server.
func (app *SimApp)

RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    clientCtx := apiSvr.ClientCtx
	/ Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ register swagger API from root so that other applications can override easily
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
}
}

/ RegisterTxService implements the Application.RegisterTxService method.
func (app *SimApp)

RegisterTxService(clientCtx client.Context) {
    authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}

/ RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *SimApp)

RegisterTendermintService(clientCtx client.Context) {
    cmtApp := server.NewCometABCIWrapper(app)

cmtservice.RegisterTendermintService(
		clientCtx,
		app.BaseApp.GRPCQueryRouter(),
		app.interfaceRegistry,
		cmtApp.Query,
	)
}

func (app *SimApp)

RegisterNodeService(clientCtx client.Context, cfg config.Config) {
    nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg)
}

/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()

map[string][]string {
    return maps.Clone(maccPerms)
}

/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()

map[string]bool {
    modAccAddrs := make(map[string]bool)
    for acc := range GetMaccPerms() {
    modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}

	/ allow the following addresses to receive funds
	delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())

return modAccAddrs
}

PreBlocker

There are two semantics around the new lifecycle method:
  • It runs before the BeginBlocker of all modules
  • It can modify consensus parameters in storage, and signal the caller through the return value.
When it returns ConsensusParamsChanged=true, the caller must refresh the consensus parameter in the finalize context:
app.finalizeBlockState.ctx = app.finalizeBlockState.ctx.WithConsensusParams(app.GetConsensusParams())
The new ctx must be passed to all the other lifecycle methods.

BeginBlocker and EndBlocker

The Cosmos SDK offers developers the possibility to implement automatic execution of code as part of their application. This is implemented through two functions called BeginBlocker and EndBlocker. They are called when the application receives the FinalizeBlock messages from the CometBFT consensus engine, which happens respectively at the beginning and at the end of each block. The application must set the BeginBlocker and EndBlocker in its constructor via the SetBeginBlocker and SetEndBlocker methods. In general, the BeginBlocker and EndBlocker functions are mostly composed of the BeginBlock and EndBlock functions of each of the application’s modules. This is done by calling the BeginBlock and EndBlock functions of the module manager, which in turn calls the BeginBlock and EndBlock functions of each of the modules it contains. Note that the order in which the modules’ BeginBlock and EndBlock functions must be called has to be set in the module manager using the SetOrderBeginBlockers and SetOrderEndBlockers methods, respectively. This is done via the module manager in the application’s constructor, and the SetOrderBeginBlockers and SetOrderEndBlockers methods have to be called before the SetBeginBlocker and SetEndBlocker functions. As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in BeginBlocker or EndBlocker, and must also be careful not to make them too computationally expensive, as gas does not constrain the cost of BeginBlocker and EndBlocker execution. See an example of BeginBlocker and EndBlocker functions from simapp
/go:build app_v1

package simapp

import (

	"encoding/json"
    "fmt"
    "io"
    "maps"

	abci "github.com/cometbft/cometbft/abci/types"
	dbm "github.com/cosmos/cosmos-db"
    "github.com/cosmos/gogoproto/proto"
    "github.com/spf13/cast"

	autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
	reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
    "cosmossdk.io/client/v2/autocli"
	clienthelpers "cosmossdk.io/client/v2/helpers"
    "cosmossdk.io/core/appmodule"
    "cosmossdk.io/log"
	storetypes "cosmossdk.io/store/types"
    "cosmossdk.io/x/circuit"
	circuitkeeper "cosmossdk.io/x/circuit/keeper"
	circuittypes "cosmossdk.io/x/circuit/types"
    "cosmossdk.io/x/evidence"
	evidencekeeper "cosmossdk.io/x/evidence/keeper"
	evidencetypes "cosmossdk.io/x/evidence/types"
    "cosmossdk.io/x/feegrant"
	feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
	feegrantmodule "cosmossdk.io/x/feegrant/module"
    "cosmossdk.io/x/nft"
	nftkeeper "cosmossdk.io/x/nft/keeper"
	nftmodule "cosmossdk.io/x/nft/module"
    "cosmossdk.io/x/tx/signing"
    "cosmossdk.io/x/upgrade"
	upgradekeeper "cosmossdk.io/x/upgrade/keeper"
	upgradetypes "cosmossdk.io/x/upgrade/types"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/client/flags"
    "github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
	nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/address"
    "github.com/cosmos/cosmos-sdk/codec/types"
    "github.com/cosmos/cosmos-sdk/runtime"
	runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
    "github.com/cosmos/cosmos-sdk/server"
    "github.com/cosmos/cosmos-sdk/server/api"
    "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    "github.com/cosmos/cosmos-sdk/std"
	testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
	sdk "github.com/cosmos/cosmos-sdk/types"
    "github.com/cosmos/cosmos-sdk/types/module"
	sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
    "github.com/cosmos/cosmos-sdk/version"
    "github.com/cosmos/cosmos-sdk/x/auth"
    "github.com/cosmos/cosmos-sdk/x/auth/ante"
	authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec"
	authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
    "github.com/cosmos/cosmos-sdk/x/auth/posthandler"
	authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
    "github.com/cosmos/cosmos-sdk/x/auth/tx"
	authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
	txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    "github.com/cosmos/cosmos-sdk/x/auth/vesting"
	vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
    "github.com/cosmos/cosmos-sdk/x/authz"
	authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
	authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
    "github.com/cosmos/cosmos-sdk/x/bank"
	bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
	consensus "github.com/cosmos/cosmos-sdk/x/consensus"
	consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
	consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
	distr "github.com/cosmos/cosmos-sdk/x/distribution"
	distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
	distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
    "github.com/cosmos/cosmos-sdk/x/epochs"
	epochskeeper "github.com/cosmos/cosmos-sdk/x/epochs/keeper"
	epochstypes "github.com/cosmos/cosmos-sdk/x/epochs/types"
    "github.com/cosmos/cosmos-sdk/x/genutil"
	genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
    "github.com/cosmos/cosmos-sdk/x/gov"
	govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
	govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
	govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    "github.com/cosmos/cosmos-sdk/x/group"
	groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
	groupmodule "github.com/cosmos/cosmos-sdk/x/group/module"
    "github.com/cosmos/cosmos-sdk/x/mint"
	mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
	minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
    "github.com/cosmos/cosmos-sdk/x/protocolpool"
	protocolpoolkeeper "github.com/cosmos/cosmos-sdk/x/protocolpool/keeper"
	protocolpooltypes "github.com/cosmos/cosmos-sdk/x/protocolpool/types"
    "github.com/cosmos/cosmos-sdk/x/slashing"
	slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
	slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
    "github.com/cosmos/cosmos-sdk/x/staking"
	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

const appName = "SimApp"

var (
	/ DefaultNodeHome default home directories for the application daemon
	DefaultNodeHome string

	/ module account permissions
	maccPerms = map[string][]string{
    authtypes.FeeCollectorName:                  nil,
		distrtypes.ModuleName:                       nil,
		minttypes.ModuleName:                        {
    authtypes.Minter
},
		stakingtypes.BondedPoolName:                 {
    authtypes.Burner, authtypes.Staking
},
		stakingtypes.NotBondedPoolName:              {
    authtypes.Burner, authtypes.Staking
},
		govtypes.ModuleName:                         {
    authtypes.Burner
},
		nft.ModuleName:                              nil,
		protocolpooltypes.ModuleName:                nil,
		protocolpooltypes.ProtocolPoolEscrowAccount: nil
}
)

var (
	_ runtime.AppI            = (*SimApp)(nil)
	_ servertypes.Application = (*SimApp)(nil)
)

/ SimApp extends an ABCI application, but with most of its parameters exported.
/ They are exported for convenience in creating helper functions, as object
/ capabilities aren't needed for testing.
type SimApp struct {
	*baseapp.BaseApp
	legacyAmino       *codec.LegacyAmino
	appCodec          codec.Codec
	txConfig          client.TxConfig
	interfaceRegistry types.InterfaceRegistry

	/ keys to access the substores
	keys map[string]*storetypes.KVStoreKey

	/ essential keepers
	AccountKeeper         authkeeper.AccountKeeper
	BankKeeper            bankkeeper.BaseKeeper
	StakingKeeper         *stakingkeeper.Keeper
	SlashingKeeper        slashingkeeper.Keeper
	MintKeeper            mintkeeper.Keeper
	DistrKeeper           distrkeeper.Keeper
	GovKeeper             govkeeper.Keeper
	UpgradeKeeper         *upgradekeeper.Keeper
	EvidenceKeeper        evidencekeeper.Keeper
	ConsensusParamsKeeper consensusparamkeeper.Keeper
	CircuitKeeper         circuitkeeper.Keeper

	/ supplementary keepers
	FeeGrantKeeper     feegrantkeeper.Keeper
	GroupKeeper        groupkeeper.Keeper
	AuthzKeeper        authzkeeper.Keeper
	NFTKeeper          nftkeeper.Keeper
	EpochsKeeper       epochskeeper.Keeper
	ProtocolPoolKeeper protocolpoolkeeper.Keeper

	/ the module manager
	ModuleManager      *module.Manager
	BasicModuleManager module.BasicManager

	/ simulation manager
	sm *module.SimulationManager

	/ module configurator
	configurator module.Configurator
}

func init() {
    var err error
	DefaultNodeHome, err = clienthelpers.GetNodeHomeDirectory(".simapp")
    if err != nil {
    panic(err)
}
}

/ NewSimApp returns a reference to an initialized SimApp.
func NewSimApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	loadLatest bool,
	appOpts servertypes.AppOptions,
	baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
    interfaceRegistry, _ := types.NewInterfaceRegistryWithOptions(types.InterfaceRegistryOptions{
    ProtoFiles: proto.HybridResolver,
    SigningOptions: signing.Options{
    AddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(),
},
    ValidatorAddressCodec: address.Bech32Codec{
    Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(),
},
},
})
    appCodec := codec.NewProtoCodec(interfaceRegistry)
    legacyAmino := codec.NewLegacyAmino()
    txConfig := tx.NewTxConfig(appCodec, tx.DefaultSignModes)
    if err := interfaceRegistry.SigningContext().Validate(); err != nil {
    panic(err)
}

std.RegisterLegacyAminoCodec(legacyAmino)

std.RegisterInterfaces(interfaceRegistry)

	/ Below we could construct and set an application specific mempool and
	/ ABCI 1.0 PrepareProposal and ProcessProposal handlers. These defaults are
	/ already set in the SDK's BaseApp, this shows an example of how to override
	/ them.
	/
	/ Example:
	/
	/ bApp := baseapp.NewBaseApp(...)
	/ nonceMempool := mempool.NewSenderNonceMempool()
	/ abciPropHandler := NewDefaultProposalHandler(nonceMempool, bApp)
	/
	/ bApp.SetMempool(nonceMempool)
	/ bApp.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/ bApp.SetProcessProposal(abciPropHandler.ProcessProposalHandler())
	/
	/ Alternatively, you can construct BaseApp options, append those to
	/ baseAppOptions and pass them to NewBaseApp.
	/
	/ Example:
	/
	/ prepareOpt = func(app *baseapp.BaseApp) {
	/ 	abciPropHandler := baseapp.NewDefaultProposalHandler(nonceMempool, app)
	/ 	app.SetPrepareProposal(abciPropHandler.PrepareProposalHandler())
	/
}
	/ baseAppOptions = append(baseAppOptions, prepareOpt)

	/ create and set dummy vote extension handler
    voteExtOp := func(bApp *baseapp.BaseApp) {
    voteExtHandler := NewVoteExtensionHandler()

voteExtHandler.SetHandlers(bApp)
}

baseAppOptions = append(baseAppOptions, voteExtOp, baseapp.SetOptimisticExecution())
    bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)

bApp.SetCommitMultiStoreTracer(traceStore)

bApp.SetVersion(version.Version)

bApp.SetInterfaceRegistry(interfaceRegistry)

bApp.SetTxEncoder(txConfig.TxEncoder())
    keys := storetypes.NewKVStoreKeys(
		authtypes.StoreKey,
		banktypes.StoreKey,
		stakingtypes.StoreKey,
		minttypes.StoreKey,
		distrtypes.StoreKey,
		slashingtypes.StoreKey,
		govtypes.StoreKey,
		consensusparamtypes.StoreKey,
		upgradetypes.StoreKey,
		feegrant.StoreKey,
		evidencetypes.StoreKey,
		circuittypes.StoreKey,
		authzkeeper.StoreKey,
		nftkeeper.StoreKey,
		group.StoreKey,
		epochstypes.StoreKey,
		protocolpooltypes.StoreKey,
	)

	/ register streaming services
    if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
    panic(err)
}
    app := &SimApp{
    BaseApp:           bApp,
		legacyAmino:       legacyAmino,
		appCodec:          appCodec,
		txConfig:          txConfig,
		interfaceRegistry: interfaceRegistry,
		keys:              keys,
}

	/ set the BaseApp's parameter store
	app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		runtime.EventService{
},
	)

bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore)

	/ add keepers
	app.AccountKeeper = authkeeper.NewAccountKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[authtypes.StoreKey]),
		authtypes.ProtoBaseAccount,
		maccPerms,
		authcodec.NewBech32Codec(sdk.Bech32MainPrefix),
		sdk.Bech32MainPrefix,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authkeeper.WithUnorderedTransactions(true),
	)

app.BankKeeper = bankkeeper.NewBaseKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[banktypes.StoreKey]),
		app.AccountKeeper,
		BlockedAddresses(),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		logger,
	)

	/ optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper)
    enabledSignModes := append(tx.DefaultSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL)
    txConfigOpts := tx.ConfigOptions{
    EnabledSignModes:           enabledSignModes,
    TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper),
}

txConfig, err := tx.NewTxConfigWithOptions(
		appCodec,
		txConfigOpts,
	)
    if err != nil {
    panic(err)
}

app.txConfig = txConfig

	app.StakingKeeper = stakingkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		authcodec.NewBech32Codec(sdk.Bech32PrefixValAddr),
		authcodec.NewBech32Codec(sdk.Bech32PrefixConsAddr),
	)

app.MintKeeper = mintkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[minttypes.StoreKey]),
		app.StakingKeeper,
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ mintkeeper.WithMintFn(mintkeeper.DefaultMintFn(minttypes.DefaultInflationCalculationFn)), custom mintFn can be added here
	)

app.ProtocolPoolKeeper = protocolpoolkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[protocolpooltypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.DistrKeeper = distrkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[distrtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		authtypes.FeeCollectorName,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		distrkeeper.WithExternalCommunityPool(app.ProtocolPoolKeeper),
	)

app.SlashingKeeper = slashingkeeper.NewKeeper(
		appCodec,
		legacyAmino,
		runtime.NewKVStoreService(keys[slashingtypes.StoreKey]),
		app.StakingKeeper,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[feegrant.StoreKey]),
		app.AccountKeeper,
	)

	/ register the staking hooks
	/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
	app.StakingKeeper.SetHooks(
		stakingtypes.NewMultiStakingHooks(
			app.DistrKeeper.Hooks(),
			app.SlashingKeeper.Hooks(),
		),
	)

app.CircuitKeeper = circuitkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[circuittypes.StoreKey]),
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		app.AccountKeeper.AddressCodec(),
	)

app.BaseApp.SetCircuitBreaker(&app.CircuitKeeper)

app.AuthzKeeper = authzkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[authzkeeper.StoreKey]),
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
	)
    groupConfig := group.DefaultConfig()
	/*
		Example of setting group params:
		groupConfig.MaxMetadataLen = 1000
	*/
	app.GroupKeeper = groupkeeper.NewKeeper(
		keys[group.StoreKey],
		appCodec,
		app.MsgServiceRouter(),
		app.AccountKeeper,
		groupConfig,
	)

	/ get skipUpgradeHeights from the app options
    skipUpgradeHeights := map[int64]bool{
}
    for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
    skipUpgradeHeights[int64(h)] = true
}
    homePath := cast.ToString(appOpts.Get(flags.FlagHome))
	/ set the governance module account as the authority for conducting upgrades
	app.UpgradeKeeper = upgradekeeper.NewKeeper(
		skipUpgradeHeights,
		runtime.NewKVStoreService(keys[upgradetypes.StoreKey]),
		appCodec,
		homePath,
		app.BaseApp,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
	)

	/ Register the proposal types
	/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
	/ by granting the governance module the right to execute the message.
	/ See: https://docs.cosmos.network/main/modules/gov#proposal-messages
    govRouter := govv1beta1.NewRouter()

govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler)
    govConfig := govtypes.DefaultConfig()
	/*
		Example of setting gov params:
		govConfig.MaxMetadataLen = 10000
	*/
    govKeeper := govkeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[govtypes.StoreKey]),
		app.AccountKeeper,
		app.BankKeeper,
		app.StakingKeeper,
		app.DistrKeeper,
		app.MsgServiceRouter(),
		govConfig,
		authtypes.NewModuleAddress(govtypes.ModuleName).String(),
		/ govkeeper.WithCustomCalculateVoteResultsAndVotingPowerFn(...), / Add if you want to use a custom vote calculation function.
	)

	/ Set legacy router for backwards compatibility with gov v1beta1
	govKeeper.SetLegacyRouter(govRouter)

app.GovKeeper = *govKeeper.SetHooks(
		govtypes.NewMultiGovHooks(
			/ register the governance hooks
		),
	)

app.NFTKeeper = nftkeeper.NewKeeper(
		runtime.NewKVStoreService(keys[nftkeeper.StoreKey]),
		appCodec,
		app.AccountKeeper,
		app.BankKeeper,
	)

	/ create evidence keeper with router
    evidenceKeeper := evidencekeeper.NewKeeper(
		appCodec,
		runtime.NewKVStoreService(keys[evidencetypes.StoreKey]),
		app.StakingKeeper,
		app.SlashingKeeper,
		app.AccountKeeper.AddressCodec(),
		runtime.ProvideCometInfoService(),
	)
	/ If evidence needs to be handled for the app, set routes in router here and seal
	app.EvidenceKeeper = *evidenceKeeper

	app.EpochsKeeper = epochskeeper.NewKeeper(
		runtime.NewKVStoreService(keys[epochstypes.StoreKey]),
		appCodec,
	)

app.EpochsKeeper.SetHooks(
		epochstypes.NewMultiEpochHooks(
			/ insert epoch hooks receivers here
		),
	)

	/****  Module Options ****/

	/ NOTE: Any module instantiated in the module manager that is later modified
	/ must be passed by reference here.
	app.ModuleManager = module.NewManager(
		genutil.NewAppModule(
			app.AccountKeeper, app.StakingKeeper, app,
			txConfig,
		),
		auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
		vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
		bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
		feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
		gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
		mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil),
		slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry),
		distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
		staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil),
		upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()),
		evidence.NewAppModule(app.EvidenceKeeper),
		authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
		consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
		circuit.NewAppModule(appCodec, app.CircuitKeeper),
		epochs.NewAppModule(app.EpochsKeeper),
		protocolpool.NewAppModule(app.ProtocolPoolKeeper, app.AccountKeeper, app.BankKeeper),
	)

	/ BasicModuleManager defines the module BasicManager is in charge of setting up basic,
	/ non-dependant module elements, such as codec registration and genesis verification.
	/ By default it is composed of all the module from the module manager.
	/ Additionally, app module basics can be overwritten by passing them as argument.
	app.BasicModuleManager = module.NewBasicManagerFromManager(
		app.ModuleManager,
		map[string]module.AppModuleBasic{
    genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
			govtypes.ModuleName: gov.NewAppModuleBasic(
				[]govclient.ProposalHandler{
},
			),
})

app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)

app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)

	/ NOTE: upgrade module is required to be prioritized
	app.ModuleManager.SetOrderPreBlockers(
		upgradetypes.ModuleName,
		authtypes.ModuleName,
	)
	/ During begin block slashing happens after distr.BeginBlocker so that
	/ there is nothing left over in the validator fee pool, so as to keep the
	/ CanWithdrawInvariant invariant.
	/ NOTE: staking module is required if HistoricalEntries param > 0
	app.ModuleManager.SetOrderBeginBlockers(
		minttypes.ModuleName,
		distrtypes.ModuleName,
		protocolpooltypes.ModuleName,
		slashingtypes.ModuleName,
		evidencetypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		authz.ModuleName,
		epochstypes.ModuleName,
	)

app.ModuleManager.SetOrderEndBlockers(
		govtypes.ModuleName,
		stakingtypes.ModuleName,
		genutiltypes.ModuleName,
		feegrant.ModuleName,
		group.ModuleName,
		protocolpooltypes.ModuleName,
	)

	/ NOTE: The genutils module must occur after staking so that pools are
	/ properly initialized with tokens from genesis accounts.
	/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
    genesisModuleOrder := []string{
    authtypes.ModuleName,
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		consensusparamtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
		protocolpooltypes.ModuleName,
}
    exportModuleOrder := []string{
    consensusparamtypes.ModuleName,
		authtypes.ModuleName,
		protocolpooltypes.ModuleName, / Must be exported before bank
		banktypes.ModuleName,
		distrtypes.ModuleName,
		stakingtypes.ModuleName,
		slashingtypes.ModuleName,
		govtypes.ModuleName,
		minttypes.ModuleName,
		genutiltypes.ModuleName,
		evidencetypes.ModuleName,
		authz.ModuleName,
		feegrant.ModuleName,
		nft.ModuleName,
		group.ModuleName,
		upgradetypes.ModuleName,
		vestingtypes.ModuleName,
		circuittypes.ModuleName,
		epochstypes.ModuleName,
}

app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)

app.ModuleManager.SetOrderExportGenesis(exportModuleOrder...)

	/ Uncomment if you want to set a custom migration order here.
	/ app.ModuleManager.SetOrderMigrations(custom order)

app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())

err = app.ModuleManager.RegisterServices(app.configurator)
    if err != nil {
    panic(err)
}

	/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
	/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
	app.RegisterUpgradeHandlers()

autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))

reflectionSvc, err := runtimeservices.NewReflectionService()
    if err != nil {
    panic(err)
}

reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)

	/ add test gRPC service for testing gRPC queries in isolation
	testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{
})

	/ create the simulation manager and define the order of the modules for deterministic simulations
	/
	/ NOTE: this is not required apps that don't use the simulator for fuzz testing
	/ transactions
    overrideModules := map[string]module.AppModuleSimulation{
    authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}

app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)

app.sm.RegisterStoreDecoders()

	/ initialize stores
	app.MountKVStores(keys)

	/ initialize BaseApp
	app.SetInitChainer(app.InitChainer)

app.SetPreBlocker(app.PreBlocker)

app.SetBeginBlocker(app.BeginBlocker)

app.SetEndBlocker(app.EndBlocker)

app.setAnteHandler(txConfig)

	/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
	/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
	/ defined as a chain, and have the same signature as antehandlers.
	/
	/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
	/ meaning that both `runMsgs` and `postHandler` state will be committed if
	/ both are successful, and both will be reverted if any of the two fails.
	/
	/ The SDK exposes a default postHandlers chain
	/
	/ Please note that changing any of the anteHandler or postHandler chain is
	/ likely to be a state-machine breaking change, which needs a coordinated
	/ upgrade.
	app.setPostHandler()
    if loadLatest {
    if err := app.LoadLatestVersion(); err != nil {
    panic(fmt.Errorf("error loading last version: %w", err))
}

}

return app
}

func (app *SimApp)

setAnteHandler(txConfig client.TxConfig) {
    anteHandler, err := NewAnteHandler(
		HandlerOptions{
    ante.HandlerOptions{
    AccountKeeper:   app.AccountKeeper,
    BankKeeper:      app.BankKeeper,
    SignModeHandler: txConfig.SignModeHandler(),
    FeegrantKeeper:  app.FeeGrantKeeper,
    SigGasConsumer:  ante.DefaultSigVerificationGasConsumer,
    SigVerifyOptions: []ante.SigVerificationDecoratorOption{
					/ change below as needed.
					ante.WithUnorderedTxGasCost(ante.DefaultUnorderedTxGasCost),
					ante.WithMaxUnorderedTxTimeoutDuration(ante.DefaultMaxTimeoutDuration),
},
},
			&app.CircuitKeeper,
},
	)
    if err != nil {
    panic(err)
}

	/ Set the AnteHandler for the app
	app.SetAnteHandler(anteHandler)
}

func (app *SimApp)

setPostHandler() {
    postHandler, err := posthandler.NewPostHandler(
		posthandler.HandlerOptions{
},
	)
    if err != nil {
    panic(err)
}

app.SetPostHandler(postHandler)
}

/ Name returns the name of the App
func (app *SimApp)

Name()

string {
    return app.BaseApp.Name()
}

/ PreBlocker application updates every pre block
func (app *SimApp)

PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
    return app.ModuleManager.PreBlock(ctx)
}

/ BeginBlocker application updates every begin block
func (app *SimApp)

BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
    return app.ModuleManager.BeginBlock(ctx)
}

/ EndBlocker application updates every end block
func (app *SimApp)

EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
    return app.ModuleManager.EndBlock(ctx)
}

func (a *SimApp)

Configurator()

module.Configurator {
    return a.configurator
}

/ InitChainer application update at chain initialization
func (app *SimApp)

InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
    var genesisState GenesisState
    if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
    panic(err)
}

app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap())

return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}

/ LoadHeight loads a particular height
func (app *SimApp)

LoadHeight(height int64)

error {
    return app.LoadVersion(height)
}

/ LegacyAmino returns SimApp's amino codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

LegacyAmino() *codec.LegacyAmino {
    return app.legacyAmino
}

/ AppCodec returns SimApp's app codec.
/
/ NOTE: This is solely to be used for testing purposes as it may be desirable
/ for modules to register their own custom testing types.
func (app *SimApp)

AppCodec()

codec.Codec {
    return app.appCodec
}

/ InterfaceRegistry returns SimApp's InterfaceRegistry
func (app *SimApp)

InterfaceRegistry()

types.InterfaceRegistry {
    return app.interfaceRegistry
}

/ TxConfig returns SimApp's TxConfig
func (app *SimApp)

TxConfig()

client.TxConfig {
    return app.txConfig
}

/ AutoCliOpts returns the autocli options for the app.
func (app *SimApp)

AutoCliOpts()

autocli.AppOptions {
    modules := make(map[string]appmodule.AppModule, 0)
    for _, m := range app.ModuleManager.Modules {
    if moduleWithName, ok := m.(module.HasName); ok {
    moduleName := moduleWithName.Name()
    if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
    modules[moduleName] = appModule
}

}

}

return autocli.AppOptions{
    Modules:               modules,
    ModuleOptions:         runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
    AddressCodec:          authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
    ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()),
    ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)

DefaultGenesis()

map[string]json.RawMessage {
    return a.BasicModuleManager.DefaultGenesis(a.appCodec)
}

/ GetKey returns the KVStoreKey for the provided store key.
/
/ NOTE: This is solely to be used for testing purposes.
func (app *SimApp)

GetKey(storeKey string) *storetypes.KVStoreKey {
    return app.keys[storeKey]
}

/ GetStoreKeys returns all the stored store keys.
func (app *SimApp)

GetStoreKeys() []storetypes.StoreKey {
    keys := make([]storetypes.StoreKey, 0, len(app.keys))
    for _, key := range app.keys {
    keys = append(keys, key)
}

return keys
}

/ SimulationManager implements the SimulationApp interface
func (app *SimApp)

SimulationManager() *module.SimulationManager {
    return app.sm
}

/ RegisterAPIRoutes registers all application module routes with the provided
/ API server.
func (app *SimApp)

RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
    clientCtx := apiSvr.ClientCtx
	/ Register new tx routes from grpc-gateway.
	authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register new CometBFT queries routes from grpc-gateway.
	cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register node gRPC service for grpc-gateway.
	nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ Register grpc-gateway routes for all modules.
	app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)

	/ register swagger API from root so that other applications can override easily
    if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
    panic(err)
}
}

/ RegisterTxService implements the Application.RegisterTxService method.
func (app *SimApp)

RegisterTxService(clientCtx client.Context) {
    authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
}

/ RegisterTendermintService implements the Application.RegisterTendermintService method.
func (app *SimApp)

RegisterTendermintService(clientCtx client.Context) {
    cmtApp := server.NewCometABCIWrapper(app)

cmtservice.RegisterTendermintService(
		clientCtx,
		app.BaseApp.GRPCQueryRouter(),
		app.interfaceRegistry,
		cmtApp.Query,
	)
}

func (app *SimApp)

RegisterNodeService(clientCtx client.Context, cfg config.Config) {
    nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg)
}

/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()

map[string][]string {
    return maps.Clone(maccPerms)
}

/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()

map[string]bool {
    modAccAddrs := make(map[string]bool)
    for acc := range GetMaccPerms() {
    modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}

	/ allow the following addresses to receive funds
	delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())

return modAccAddrs
}

Register Codec

The EncodingConfig structure is the last important part of the app.go file. The goal of this structure is to define the codecs that will be used throughout the app.
package params

import (

	"github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/types"
)

/ EncodingConfig specifies the concrete encoding types to use for a given app.
/ This is provided for compatibility between protobuf and amino implementations.
type EncodingConfig struct {
    InterfaceRegistry types.InterfaceRegistry
	Codec             codec.Codec
	TxConfig          client.TxConfig
	Amino             *codec.LegacyAmino
}
Here are descriptions of what each of the four fields means:
  • InterfaceRegistry: The InterfaceRegistry is used by the Protobuf codec to handle interfaces that are encoded and decoded (we also say “unpacked”) using google.protobuf.Any. Any could be thought as a struct that contains a type_url (name of a concrete type implementing the interface) and a value (its encoded bytes). InterfaceRegistry provides a mechanism for registering interfaces and implementations that can be safely unpacked from Any. Each application module implements the RegisterInterfaces method that can be used to register the module’s own interfaces and implementations.
    • You can read more about Any in ADR-019.
    • To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called gogoprotobuf. By default, the gogo protobuf implementation of Any uses global type registration to decode values packed in Any into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in the type_url field. For more information, please refer to ADR-019.
  • Codec: The default codec used throughout the Cosmos SDK. It is composed of a BinaryCodec used to encode and decode state, and a JSONCodec used to output data to the users (for example, in the CLI). By default, the SDK uses Protobuf as Codec.
  • TxConfig: TxConfig defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types: SIGN_MODE_DIRECT (which uses Protobuf binary as over-the-wire encoding) and SIGN_MODE_LEGACY_AMINO_JSON (which depends on Amino). Read more about transactions here.
  • Amino: Some legacy parts of the Cosmos SDK still use Amino for backwards-compatibility. Each module exposes a RegisterLegacyAmino method to register the module’s specific types within Amino. This Amino codec should not be used by app developers anymore, and will be removed in future releases.
An application should create its own encoding config. See an example of a simappparams.EncodingConfig from simapp:
package params

import (

	"github.com/cosmos/cosmos-sdk/client"
    "github.com/cosmos/cosmos-sdk/codec"
    "github.com/cosmos/cosmos-sdk/codec/types"
)

/ EncodingConfig specifies the concrete encoding types to use for a given app.
/ This is provided for compatibility between protobuf and amino implementations.
type EncodingConfig struct {
    InterfaceRegistry types.InterfaceRegistry
	Codec             codec.Codec
	TxConfig          client.TxConfig
	Amino             *codec.LegacyAmino
}

Modules

Modules are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed by baseapp to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application. In the application directory, the standard practice is to store modules in the x/ folder (not to be confused with the Cosmos SDK’s x/ folder, which contains already-built modules).

Application Module Interface

Modules must implement interfaces defined in the Cosmos SDK, AppModuleBasic and AppModule. The former implements basic non-dependent elements of the module, such as the codec, while the latter handles the bulk of the module methods (including methods that require references to other modules’ keepers). Both the AppModule and AppModuleBasic types are, by convention, defined in a file called module.go. AppModule exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the module manager, which manages the application’s collection of modules.

Msg Services

Each application module defines two Protobuf services: one Msg service to handle messages, and one gRPC Query service to handle queries. If we consider the module as a state-machine, then a Msg service is a set of state transition RPC methods. Each Protobuf Msg service method is 1:1 related to a Protobuf request type, which must implement sdk.Msg interface. Note that sdk.Msgs are bundled in transactions, and each transaction contains one or multiple messages. When a valid block of transactions is received by the full-node, CometBFT relays each one to the application via DeliverTx. Then, the application handles the transaction:
  1. Upon receiving the transaction, the application first unmarshalls it from []byte.
  2. Then, it verifies a few things about the transaction like fee payment and signatures before extracting the Msg(s) contained in the transaction.
  3. sdk.Msgs are encoded using Protobuf Anys. By analyzing each Any’s type_url, baseapp’s msgServiceRouter routes the sdk.Msg to the corresponding module’s Msg service.
  4. If the message is successfully processed, the state is updated.
For more details, see transaction lifecycle. Module developers create custom Msg services when they build their own module. The general practice is to define the Msg Protobuf service in a tx.proto file. For example, the x/bank module defines a service with two methods to transfer tokens:
// Msg defines the bank Msg service.
service Msg {
  option (cosmos.msg.v1.service) = true;

  // Send defines a method for sending coins from one account to another account.
  rpc Send(MsgSend) returns (MsgSendResponse);

  // MultiSend defines a method for sending coins from some accounts to other accounts.
  rpc MultiSend(MsgMultiSend) returns (MsgMultiSendResponse);

  // UpdateParams defines a governance operation for updating the x/bank module parameters.
  // The authority is defined in the keeper.
  rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse) {
    option (cosmos_proto.method_added_in) = "cosmos-sdk 0.47";
  };

  // SetSendEnabled is a governance operation for setting the SendEnabled flag
  // on any number of Denoms. Only the entries to add or update should be
  // included. Entries that already exist in the store, but that aren't
  // included in this message, will be left unchanged.
  rpc SetSendEnabled(MsgSetSendEnabled) returns (MsgSetSendEnabledResponse) {
    option (cosmos_proto.method_added_in) = "cosmos-sdk 0.47";
  };
}
Service methods use keeper in order to update the module state. Each module should also implement the RegisterServices method as part of the AppModule interface. This method should call the RegisterMsgServer function provided by the generated Protobuf code.

gRPC Query Services

gRPC Query services allow users to query the state using gRPC. They are enabled by default, and can be configured under the grpc.enable and grpc.address fields inside app.toml. gRPC Query services are defined in the module’s Protobuf definition files, specifically inside query.proto. The query.proto definition file exposes a single Query Protobuf service. Each gRPC query endpoint corresponds to a service method, starting with the rpc keyword, inside the Query service. Protobuf generates a QueryServer interface for each module, containing all the service methods. A module’s keeper then needs to implement this QueryServer interface, by providing the concrete implementation of each service method. This concrete implementation is the handler of the corresponding gRPC query endpoint. Finally, each module should also implement the RegisterServices method as part of the AppModule interface. This method should call the RegisterQueryServer function provided by the generated Protobuf code.

Keeper

Keepers are the gatekeepers of their module’s store(s). To read or write in a module’s store, it is mandatory to go through one of its keeper’s methods. This is ensured by the object-capabilities model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module’s keeper should hold the key(s) to the module’s store(s). Keepers are generally defined in a file called keeper.go. It contains the keeper’s type definition and methods. The keeper type definition generally consists of the following:
  • Key(s) to the module’s store(s) in the multistore.
  • Reference to other module’s keepers. Only needed if the keeper needs to access other module’s store(s) (either to read or write from them).
  • A reference to the application’s codec. The keeper needs it to marshal structs before storing them, or to unmarshal them when it retrieves them, because stores only accept []bytes as value.
Along with the type definition, the next important component of the keeper.go file is the keeper’s constructor function, NewKeeper. This function instantiates a new keeper of the type defined above with a codec, stores keys and potentially references other modules’ keepers as parameters. The NewKeeper function is called from the application’s constructor. The rest of the file defines the keeper’s methods, which are primarily getters and setters.

Command-Line, gRPC Services and REST Interfaces

Each module defines command-line commands, gRPC services, and REST routes to be exposed to the end-user via the application’s interfaces. This enables end-users to create messages of the types defined in the module, or to query the subset of the state managed by the module.

CLI

Generally, the commands related to a module are defined in a folder called client/cli in the module’s folder. The CLI divides commands into two categories, transactions and queries, defined in client/cli/tx.go and client/cli/query.go, respectively. Both commands are built on top of the Cobra Library:
  • Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each message type defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The Cosmos SDK handles signing and the addition of other transaction metadata.
  • Queries let users query the subset of the state defined by the module. Query commands forward queries to the application’s query router, which routes them to the appropriate querier the queryRoute parameter supplied.

gRPC

gRPC is a modern open-source high performance RPC framework that has support in multiple languages. It is the recommended way for external clients (such as wallets, browsers and other backend services) to interact with a node. Each module can expose gRPC endpoints called service methods, which are defined in the module’s Protobuf query.proto file. A service method is defined by its name, input arguments, and output response. The module then needs to perform the following actions:
  • Define a RegisterGRPCGatewayRoutes method on AppModuleBasic to wire the client gRPC requests to the correct handler inside the module.
  • For each service method, define a corresponding handler. The handler implements the core logic necessary to serve the gRPC request, and is located in the keeper/grpc_query.go file.

gRPC-gateway REST Endpoints

Some external clients may not wish to use gRPC. In this case, the Cosmos SDK provides a gRPC gateway service, which exposes each gRPC service as a corresponding REST endpoint. Please refer to the grpc-gateway documentation to learn more. The REST endpoints are defined in the Protobuf files, along with the gRPC services, using Protobuf annotations. Modules that want to expose REST queries should add google.api.http annotations to their rpc methods. By default, all REST endpoints defined in the SDK have a URL starting with the /cosmos/ prefix. The Cosmos SDK also provides a development endpoint to generate Swagger definition files for these REST endpoints. This endpoint can be enabled inside the app.toml config file, under the api.swagger key.

Application Interface

Interfaces let end-users interact with full-node clients. This means querying data from the full-node or creating and sending new transactions to be relayed by the full-node and eventually included in a block. The main interface is the Command-Line Interface. The CLI of a Cosmos SDK application is built by aggregating CLI commands defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g. appd), and is defined in a file called appd/main.go. The file contains the following:
  • A main() function, which is executed to build the appd interface client. This function prepares each command and adds them to the rootCmd before building them. At the root of appd, the function adds generic commands like status, keys, and config, query commands, tx commands, and rest-server.
  • Query commands, which are added by calling the queryCmd function. This function returns a Cobra command that contains the query commands defined in each of the application’s modules (passed as an array of sdk.ModuleClients from the main() function), as well as some other lower level query commands such as block or validator queries. Query command are called by using the command appd query [query] of the CLI.
  • Transaction commands, which are added by calling the txCmd function. Similar to queryCmd, the function returns a Cobra command that contains the tx commands defined in each of the application’s modules, as well as lower level tx commands like transaction signing or broadcasting. Tx commands are called by using the command appd tx [tx] of the CLI.
See an example of an application’s main command-line file from the Cosmos Hub.
package cmd

import (

	"errors"
    "io"
    "os"
    "path/filepath"
    "github.com/cosmos/cosmos-sdk/baseapp"
    "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/flags"
    "github.com/cosmos/cosmos-sdk/client/keys"
    "github.com/cosmos/cosmos-sdk/client/rpc"
    "github.com/cosmos/cosmos-sdk/server"
	serverconfig "github.com/cosmos/cosmos-sdk/server/config"
	servertypes "github.com/cosmos/cosmos-sdk/server/types"
    "github.com/cosmos/cosmos-sdk/snapshots"
	snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
    "github.com/cosmos/cosmos-sdk/store"
	sdk "github.com/cosmos/cosmos-sdk/types"
	authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
    "github.com/cosmos/cosmos-sdk/x/auth/types"
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
    "github.com/cosmos/cosmos-sdk/x/crisis"
	genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
    "github.com/spf13/cast"
    "github.com/spf13/cobra"
	tmcfg "github.com/tendermint/tendermint/config"
	tmcli "github.com/tendermint/tendermint/libs/cli"
    "github.com/tendermint/tendermint/libs/log"
	dbm "github.com/tendermint/tm-db"

	gaia "github.com/cosmos/gaia/v8/app"
    "github.com/cosmos/gaia/v8/app/params"
)

/ NewRootCmd creates a new root command for simd. It is called once in the
/ main function.
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
    encodingConfig := gaia.MakeTestEncodingConfig()
    initClientCtx := client.Context{
}.
		WithCodec(encodingConfig.Codec).
		WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
		WithTxConfig(encodingConfig.TxConfig).
		WithLegacyAmino(encodingConfig.Amino).
		WithInput(os.Stdin).
		WithAccountRetriever(types.AccountRetriever{
}).
		WithHomeDir(gaia.DefaultNodeHome).
		WithViper("")
    rootCmd := &cobra.Command{
    Use:   "gaiad",
    Short: "Stargate Cosmos Hub App",
    PersistentPreRunE: func(cmd *cobra.Command, _ []string)

error {
    initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags())
    if err != nil {
    return err
}

initClientCtx, err = config.ReadFromClientConfig(initClientCtx)
    if err != nil {
    return err
}
    if err = client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil {
    return err
}

customTemplate, customGaiaConfig := initAppConfig()
    customTMConfig := initTendermintConfig()

return server.InterceptConfigsPreRunHandler(cmd, customTemplate, customGaiaConfig, customTMConfig)
},
}

initRootCmd(rootCmd, encodingConfig)

return rootCmd, encodingConfig
}

/ initTendermintConfig helps to override default Tendermint Config values.
/ return tmcfg.DefaultConfig if no custom configuration is required for the application.
func initTendermintConfig() *tmcfg.Config {
    cfg := tmcfg.DefaultConfig()

	/ these values put a higher strain on node memory
	/ cfg.P2P.MaxNumInboundPeers = 100
	/ cfg.P2P.MaxNumOutboundPeers = 40

	return cfg
}

func initAppConfig() (string, interface{
}) {
    srvCfg := serverconfig.DefaultConfig()

srvCfg.StateSync.SnapshotInterval = 1000
	srvCfg.StateSync.SnapshotKeepRecent = 10

	return params.CustomConfigTemplate(), params.CustomAppConfig{
    Config:               *srvCfg,
    BypassMinFeeMsgTypes: gaia.GetDefaultBypassFeeMessages(),
}
}

func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
    cfg := sdk.GetConfig()

cfg.Seal()

rootCmd.AddCommand(
		genutilcli.InitCmd(gaia.ModuleBasics, gaia.DefaultNodeHome),
		genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{
}, gaia.DefaultNodeHome),
		genutilcli.GenTxCmd(gaia.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{
}, gaia.DefaultNodeHome),
		genutilcli.ValidateGenesisCmd(gaia.ModuleBasics),
		AddGenesisAccountCmd(gaia.DefaultNodeHome),
		tmcli.NewCompletionCmd(rootCmd, true),
		testnetCmd(gaia.ModuleBasics, banktypes.GenesisBalancesIterator{
}),
		debug.Cmd(),
		config.Cmd(),
	)
    ac := appCreator{
    encCfg: encodingConfig,
}

server.AddCommands(rootCmd, gaia.DefaultNodeHome, ac.newApp, ac.appExport, addModuleInitFlags)

	/ add keybase, auxiliary RPC, query, and tx child commands
	rootCmd.AddCommand(
		rpc.StatusCommand(),
		queryCommand(),
		txCommand(),
		keys.Commands(gaia.DefaultNodeHome),
	)

rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec))
}

func addModuleInitFlags(startCmd *cobra.Command) {
    crisis.AddModuleInitFlags(startCmd)
}

func queryCommand() *cobra.Command {
    cmd := &cobra.Command{
    Use:                        "query",
    Aliases:                    []string{"q"
},
    Short:                      "Querying subcommands",
    DisableFlagParsing:         true,
    SuggestionsMinimumDistance: 2,
    RunE:                       client.ValidateCmd,
}

cmd.AddCommand(
		authcmd.GetAccountCmd(),
		rpc.ValidatorCommand(),
		rpc.BlockCommand(),
		authcmd.QueryTxsByEventsCmd(),
		authcmd.QueryTxCmd(),
	)

gaia.ModuleBasics.AddQueryCommands(cmd)

cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")

return cmd
}

func txCommand() *cobra.Command {
    cmd := &cobra.Command{
    Use:                        "tx",
    Short:                      "Transactions subcommands",
    DisableFlagParsing:         true,
    SuggestionsMinimumDistance: 2,
    RunE:                       client.ValidateCmd,
}

cmd.AddCommand(
		authcmd.GetSignCommand(),
		authcmd.GetSignBatchCommand(),
		authcmd.GetMultiSignCommand(),
		authcmd.GetMultiSignBatchCmd(),
		authcmd.GetValidateSignaturesCommand(),
		flags.LineBreak,
		authcmd.GetBroadcastCommand(),
		authcmd.GetEncodeCommand(),
		authcmd.GetDecodeCommand(),
		authcmd.GetAuxToFeeCommand(),
	)

gaia.ModuleBasics.AddTxCommands(cmd)

cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")

return cmd
}

type appCreator struct {
    encCfg params.EncodingConfig
}

func (ac appCreator)

newApp(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	appOpts servertypes.AppOptions,
)

servertypes.Application {
    var cache sdk.MultiStorePersistentCache
    if cast.ToBool(appOpts.Get(server.FlagInterBlockCache)) {
    cache = store.NewCommitKVStoreCacheManager()
}
    skipUpgradeHeights := make(map[int64]bool)
    for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
    skipUpgradeHeights[int64(h)] = true
}

pruningOpts, err := server.GetPruningOptionsFromFlags(appOpts)
    if err != nil {
    panic(err)
}
    snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")

snapshotDB, err := dbm.NewDB("metadata", server.GetAppDBBackend(appOpts), snapshotDir)
    if err != nil {
    panic(err)
}

snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir)
    if err != nil {
    panic(err)
}
    snapshotOptions := snapshottypes.NewSnapshotOptions(
		cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval)),
		cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent)),
	)

return gaia.NewGaiaApp(
		logger, db, traceStore, true, skipUpgradeHeights,
		cast.ToString(appOpts.Get(flags.FlagHome)),
		cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
		ac.encCfg,
		appOpts,
		baseapp.SetPruning(pruningOpts),
		baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))),
		baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(server.FlagHaltHeight))),
		baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(server.FlagHaltTime))),
		baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(server.FlagMinRetainBlocks))),
		baseapp.SetInterBlockCache(cache),
		baseapp.SetTrace(cast.ToBool(appOpts.Get(server.FlagTrace))),
		baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))),
		baseapp.SetSnapshot(snapshotStore, snapshotOptions),
	)
}

func (ac appCreator)

appExport(
	logger log.Logger,
	db dbm.DB,
	traceStore io.Writer,
	height int64,
    forZeroHeight bool,
	jailAllowedAddrs []string,
	appOpts servertypes.AppOptions,
) (servertypes.ExportedApp, error) {
    homePath, ok := appOpts.Get(flags.FlagHome).(string)
    if !ok || homePath == "" {
    return servertypes.ExportedApp{
}, errors.New("application home is not set")
}

var loadLatest bool
    if height == -1 {
    loadLatest = true
}
    gaiaApp := gaia.NewGaiaApp(
		logger,
		db,
		traceStore,
		loadLatest,
		map[int64]bool{
},
		homePath,
		cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
		ac.encCfg,
		appOpts,
	)
    if height != -1 {
    if err := gaiaApp.LoadHeight(height); err != nil {
    return servertypes.ExportedApp{
}, err
}

}

return gaiaApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs)
}

Dependencies and Makefile

This section is optional, as developers are free to choose their dependency manager and project building method. That said, the current most used framework for versioning control is go.mod. It ensures each of the libraries used throughout the application are imported with the correct version. The following is the go.mod of the Cosmos Hub, provided as an example.
module github.com/cosmos/gaia/v8

go 1.18

require (
	cosmossdk.io/math v1.0.0-beta.3
	github.com/cosmos/cosmos-sdk v0.46.2
	github.com/cosmos/go-bip39 v1.0.0 / indirect
	github.com/cosmos/ibc-go/v5 v5.0.0
	github.com/gogo/protobuf v1.3.3
	github.com/golang/protobuf v1.5.2
	github.com/golangci/golangci-lint v1.50.0
	github.com/gorilla/mux v1.8.0
	github.com/gravity-devs/liquidity/v2 v2.0.0
	github.com/grpc-ecosystem/grpc-gateway v1.16.0
	github.com/pkg/errors v0.9.1
	github.com/rakyll/statik v0.1.7
	github.com/spf13/cast v1.5.0
	github.com/spf13/cobra v1.6.0
	github.com/spf13/pflag v1.0.5
	github.com/spf13/viper v1.13.0
	github.com/strangelove-ventures/packet-forward-middleware/v2 v2.1.4-0.20220802012200-5a62a55a7f1d
	github.com/stretchr/testify v1.8.0
	github.com/tendermint/tendermint v0.34.21
	github.com/tendermint/tm-db v0.6.7
	google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959
	google.golang.org/grpc v1.50.0
)

require (
	4d63.com/gochecknoglobals v0.1.0 / indirect
	cloud.google.com/go v0.102.1 / indirect
	cloud.google.com/go/compute v1.7.0 / indirect
	cloud.google.com/go/iam v0.4.0 / indirect
	cloud.google.com/go/storage v1.22.1 / indirect
	cosmossdk.io/errors v1.0.0-beta.7 / indirect
	filippo.io/edwards25519 v1.0.0-rc.1 / indirect
	github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 / indirect
	github.com/99designs/keyring v1.2.1 / indirect
	github.com/Abirdcfly/dupword v0.0.7 / indirect
	github.com/Antonboom/errname v0.1.7 / indirect
	github.com/Antonboom/nilnil v0.1.1 / indirect
	github.com/BurntSushi/toml v1.2.0 / indirect
	github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d / indirect
	github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 / indirect
	github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 / indirect
	github.com/Masterminds/semver v1.5.0 / indirect
	github.com/OpenPeeDeeP/depguard v1.1.1 / indirect
	github.com/Workiva/go-datastructures v1.0.53 / indirect
	github.com/alexkohler/prealloc v1.0.0 / indirect
	github.com/alingse/asasalint v0.0.11 / indirect
	github.com/armon/go-metrics v0.4.0 / indirect
	github.com/ashanbrown/forbidigo v1.3.0 / indirect
	github.com/ashanbrown/makezero v1.1.1 / indirect
	github.com/aws/aws-sdk-go v1.40.45 / indirect
	github.com/beorn7/perks v1.0.1 / indirect
	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d / indirect
	github.com/bgentry/speakeasy v0.1.0 / indirect
	github.com/bkielbasa/cyclop v1.2.0 / indirect
	github.com/blizzy78/varnamelen v0.8.0 / indirect
	github.com/bombsimon/wsl/v3 v3.3.0 / indirect
	github.com/breml/bidichk v0.2.3 / indirect
	github.com/breml/errchkjson v0.3.0 / indirect
	github.com/btcsuite/btcd v0.22.1 / indirect
	github.com/butuzov/ireturn v0.1.1 / indirect
	github.com/cenkalti/backoff/v4 v4.1.3 / indirect
	github.com/cespare/xxhash v1.1.0 / indirect
	github.com/cespare/xxhash/v2 v2.1.2 / indirect
	github.com/charithe/durationcheck v0.0.9 / indirect
	github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 / indirect
	github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e / indirect
	github.com/cockroachdb/apd/v2 v2.0.2 / indirect
	github.com/coinbase/rosetta-sdk-go v0.7.9 / indirect
	github.com/confio/ics23/go v0.7.0 / indirect
	github.com/cosmos/btcutil v1.0.4 / indirect
	github.com/cosmos/cosmos-proto v1.0.0-alpha7 / indirect
	github.com/cosmos/gorocksdb v1.2.0 / indirect
	github.com/cosmos/iavl v0.19.2-0.20220916140702-9b6be3095313 / indirect
	github.com/cosmos/ledger-cosmos-go v0.11.1 / indirect
	github.com/cosmos/ledger-go v0.9.3 / indirect
	github.com/creachadair/taskgroup v0.3.2 / indirect
	github.com/curioswitch/go-reassign v0.2.0 / indirect
	github.com/daixiang0/gci v0.8.0 / indirect
	github.com/danieljoos/wincred v1.1.2 / indirect
	github.com/davecgh/go-spew v1.1.1 / indirect
	github.com/denis-tingaikin/go-header v0.4.3 / indirect
	github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f / indirect
	github.com/dgraph-io/badger/v2 v2.2007.4 / indirect
	github.com/dgraph-io/ristretto v0.1.0 / indirect
	github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 / indirect
	github.com/dustin/go-humanize v1.0.0 / indirect
	github.com/dvsekhvalnov/jose2go v1.5.0 / indirect
	github.com/esimonov/ifshort v1.0.4 / indirect
	github.com/ettle/strcase v0.1.1 / indirect
	github.com/fatih/color v1.13.0 / indirect
	github.com/fatih/structtag v1.2.0 / indirect
	github.com/felixge/httpsnoop v1.0.1 / indirect
	github.com/firefart/nonamedreturns v1.0.4 / indirect
	github.com/fsnotify/fsnotify v1.5.4 / indirect
	github.com/fzipp/gocyclo v0.6.0 / indirect
	github.com/go-critic/go-critic v0.6.5 / indirect
	github.com/go-kit/kit v0.12.0 / indirect
	github.com/go-kit/log v0.2.1 / indirect
	github.com/go-logfmt/logfmt v0.5.1 / indirect
	github.com/go-playground/validator/v10 v10.4.1 / indirect
	github.com/go-toolsmith/astcast v1.0.0 / indirect
	github.com/go-toolsmith/astcopy v1.0.2 / indirect
	github.com/go-toolsmith/astequal v1.0.3 / indirect
	github.com/go-toolsmith/astfmt v1.0.0 / indirect
	github.com/go-toolsmith/astp v1.0.0 / indirect
	github.com/go-toolsmith/strparse v1.0.0 / indirect
	github.com/go-toolsmith/typep v1.0.2 / indirect
	github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b / indirect
	github.com/gobwas/glob v0.2.3 / indirect
	github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 / indirect
	github.com/gofrs/flock v0.8.1 / indirect
	github.com/gogo/gateway v1.1.0 / indirect
	github.com/golang/glog v1.0.0 / indirect
	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da / indirect
	github.com/golang/snappy v0.0.4 / indirect
	github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 / indirect
	github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a / indirect
	github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe / indirect
	github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 / indirect
	github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 / indirect
	github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca / indirect
	github.com/golangci/misspell v0.3.5 / indirect
	github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 / indirect
	github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 / indirect
	github.com/google/btree v1.0.1 / indirect
	github.com/google/go-cmp v0.5.9 / indirect
	github.com/google/orderedcode v0.0.1 / indirect
	github.com/google/uuid v1.3.0 / indirect
	github.com/googleapis/enterprise-certificate-proxy v0.1.0 / indirect
	github.com/googleapis/gax-go/v2 v2.4.0 / indirect
	github.com/googleapis/go-type-adapters v1.0.0 / indirect
	github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 / indirect
	github.com/gorilla/handlers v1.5.1 / indirect
	github.com/gorilla/websocket v1.5.0 / indirect
	github.com/gostaticanalysis/analysisutil v0.7.1 / indirect
	github.com/gostaticanalysis/comment v1.4.2 / indirect
	github.com/gostaticanalysis/forcetypeassert v0.1.0 / indirect
	github.com/gostaticanalysis/nilerr v0.1.1 / indirect
	github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 / indirect
	github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 / indirect
	github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c / indirect
	github.com/gtank/merlin v0.1.1 / indirect
	github.com/gtank/ristretto255 v0.1.2 / indirect
	github.com/hashicorp/errwrap v1.1.0 / indirect
	github.com/hashicorp/go-cleanhttp v0.5.2 / indirect
	github.com/hashicorp/go-getter v1.6.1 / indirect
	github.com/hashicorp/go-immutable-radix v1.3.1 / indirect
	github.com/hashicorp/go-multierror v1.1.1 / indirect
	github.com/hashicorp/go-safetemp v1.0.0 / indirect
	github.com/hashicorp/go-version v1.6.0 / indirect
	github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d / indirect
	github.com/hashicorp/hcl v1.0.0 / indirect
	github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 / indirect
	github.com/hexops/gotextdiff v1.0.3 / indirect
	github.com/improbable-eng/grpc-web v0.15.0 / indirect
	github.com/inconshreveable/mousetrap v1.0.1 / indirect
	github.com/jgautheron/goconst v1.5.1 / indirect
	github.com/jingyugao/rowserrcheck v1.1.1 / indirect
	github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af / indirect
	github.com/jmespath/go-jmespath v0.4.0 / indirect
	github.com/jmhodges/levigo v1.0.0 / indirect
	github.com/julz/importas v0.1.0 / indirect
	github.com/kisielk/errcheck v1.6.2 / indirect
	github.com/kisielk/gotool v1.0.0 / indirect
	github.com/kkHAIKE/contextcheck v1.1.2 / indirect
	github.com/klauspost/compress v1.15.9 / indirect
	github.com/kulti/thelper v0.6.3 / indirect
	github.com/kunwardeep/paralleltest v1.0.6 / indirect
	github.com/kyoh86/exportloopref v0.1.8 / indirect
	github.com/ldez/gomoddirectives v0.2.3 / indirect
	github.com/ldez/tagliatelle v0.3.1 / indirect
	github.com/leonklingele/grouper v1.1.0 / indirect
	github.com/lib/pq v1.10.6 / indirect
	github.com/libp2p/go-buffer-pool v0.1.0 / indirect
	github.com/lufeee/execinquery v1.2.1 / indirect
	github.com/magiconair/properties v1.8.6 / indirect
	github.com/manifoldco/promptui v0.9.0 / indirect
	github.com/maratori/testableexamples v1.0.0 / indirect
	github.com/maratori/testpackage v1.1.0 / indirect
	github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 / indirect
	github.com/mattn/go-colorable v0.1.13 / indirect
	github.com/mattn/go-isatty v0.0.16 / indirect
	github.com/mattn/go-runewidth v0.0.9 / indirect
	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 / indirect
	github.com/mbilski/exhaustivestruct v1.2.0 / indirect
	github.com/mgechev/revive v1.2.4 / indirect
	github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 / indirect
	github.com/minio/highwayhash v1.0.2 / indirect
	github.com/mitchellh/go-homedir v1.1.0 / indirect
	github.com/mitchellh/go-testing-interface v1.0.0 / indirect
	github.com/mitchellh/mapstructure v1.5.0 / indirect
	github.com/moricho/tparallel v0.2.1 / indirect
	github.com/mtibben/percent v0.2.1 / indirect
	github.com/nakabonne/nestif v0.3.1 / indirect
	github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 / indirect
	github.com/nishanths/exhaustive v0.8.3 / indirect
	github.com/nishanths/predeclared v0.2.2 / indirect
	github.com/olekukonko/tablewriter v0.0.5 / indirect
	github.com/pelletier/go-toml v1.9.5 / indirect
	github.com/pelletier/go-toml/v2 v2.0.5 / indirect
	github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 / indirect
	github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d / indirect
	github.com/pmezard/go-difflib v1.0.0 / indirect
	github.com/polyfloyd/go-errorlint v1.0.5 / indirect
	github.com/prometheus/client_golang v1.12.2 / indirect
	github.com/prometheus/client_model v0.2.0 / indirect
	github.com/prometheus/common v0.34.0 / indirect
	github.com/prometheus/procfs v0.7.3 / indirect
	github.com/quasilyte/go-ruleguard v0.3.18 / indirect
	github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f / indirect
	github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 / indirect
	github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 / indirect
	github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 / indirect
	github.com/regen-network/cosmos-proto v0.3.1 / indirect
	github.com/rs/cors v1.8.2 / indirect
	github.com/rs/zerolog v1.27.0 / indirect
	github.com/ryancurrah/gomodguard v1.2.4 / indirect
	github.com/ryanrolds/sqlclosecheck v0.3.0 / indirect
	github.com/sanposhiho/wastedassign/v2 v2.0.6 / indirect
	github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa / indirect
	github.com/sashamelentyev/interfacebloat v1.1.0 / indirect
	github.com/sashamelentyev/usestdlibvars v1.20.0 / indirect
	github.com/securego/gosec/v2 v2.13.1 / indirect
	github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c / indirect
	github.com/sirupsen/logrus v1.9.0 / indirect
	github.com/sivchari/containedctx v1.0.2 / indirect
	github.com/sivchari/nosnakecase v1.7.0 / indirect
	github.com/sivchari/tenv v1.7.0 / indirect
	github.com/sonatard/noctx v0.0.1 / indirect
	github.com/sourcegraph/go-diff v0.6.1 / indirect
	github.com/spf13/afero v1.8.2 / indirect
	github.com/spf13/jwalterweatherman v1.1.0 / indirect
	github.com/ssgreg/nlreturn/v2 v2.2.1 / indirect
	github.com/stbenjam/no-sprintf-host-port v0.1.1 / indirect
	github.com/stretchr/objx v0.4.0 / indirect
	github.com/subosito/gotenv v1.4.1 / indirect
	github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 / indirect
	github.com/tdakkota/asciicheck v0.1.1 / indirect
	github.com/tendermint/btcd v0.1.1 / indirect
	github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 / indirect
	github.com/tendermint/go-amino v0.16.0 / indirect
	github.com/tetafro/godot v1.4.11 / indirect
	github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 / indirect
	github.com/timonwong/loggercheck v0.9.3 / indirect
	github.com/tomarrell/wrapcheck/v2 v2.6.2 / indirect
	github.com/tommy-muehle/go-mnd/v2 v2.5.0 / indirect
	github.com/ulikunitz/xz v0.5.8 / indirect
	github.com/ultraware/funlen v0.0.3 / indirect
	github.com/ultraware/whitespace v0.0.5 / indirect
	github.com/uudashr/gocognit v1.0.6 / indirect
	github.com/yagipy/maintidx v1.0.0 / indirect
	github.com/yeya24/promlinter v0.2.0 / indirect
	github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 / indirect
	gitlab.com/bosi/decorder v0.2.3 / indirect
	go.etcd.io/bbolt v1.3.6 / indirect
	go.opencensus.io v0.23.0 / indirect
	go.uber.org/atomic v1.9.0 / indirect
	go.uber.org/multierr v1.8.0 / indirect
	go.uber.org/zap v1.21.0 / indirect
	golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa / indirect
	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e / indirect
	golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 / indirect
	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 / indirect
	golang.org/x/net v0.0.0-20220726230323-06994584191e / indirect
	golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 / indirect
	golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde / indirect
	golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 / indirect
	golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 / indirect
	golang.org/x/text v0.3.7 / indirect
	golang.org/x/tools v0.1.12 / indirect
	golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f / indirect
	google.golang.org/api v0.93.0 / indirect
	google.golang.org/appengine v1.6.7 / indirect
	google.golang.org/protobuf v1.28.1 / indirect
	gopkg.in/ini.v1 v1.67.0 / indirect
	gopkg.in/yaml.v2 v2.4.0 / indirect
	gopkg.in/yaml.v3 v3.0.1 / indirect
	honnef.co/go/tools v0.3.3 / indirect
	mvdan.cc/gofumpt v0.4.0 / indirect
	mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed / indirect
	mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b / indirect
	mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 / indirect
	nhooyr.io/websocket v1.8.6 / indirect
	sigs.k8s.io/yaml v1.3.0 / indirect
)

replace (
	github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
	github.com/zondax/hid => github.com/zondax/hid v0.9.0
)
For building the application, a Makefile is generally used. The Makefile primarily ensures that the go.mod is run before building the two entrypoints to the application, Node Client and Application Interface. Here is an example of the Cosmos Hub Makefile.