refactor!: kill basic manager (#19512)
This commit is contained in:
@@ -349,7 +349,7 @@ type TxBuilder interface {
|
||||
```
|
||||
|
||||
We then update `Context` to have new fields: `Codec`, `TxGenerator`,
|
||||
and `AccountRetriever`, and we update `AppModuleBasic.GetTxCmd` to take
|
||||
and `AccountRetriever`, and we update `AppModule.GetTxCmd` to take
|
||||
a `Context` which should have all of these fields pre-populated.
|
||||
|
||||
Each client method should then use one of the `Init` methods to re-initialize
|
||||
|
||||
@@ -261,7 +261,7 @@ func TxEmitter(ctx context.Context, cliCtx client.Context, ehs ...EventHandler)
|
||||
}
|
||||
|
||||
// PublishChainTxEvents events using cmtclient. Waits on context shutdown signals to exit.
|
||||
func PublishChainTxEvents(ctx context.Context, client cmtclient.EventsClient, bus pubsub.Bus, mb module.BasicManager) (err error) {
|
||||
func PublishChainTxEvents(ctx context.Context, client cmtclient.EventsClient, bus pubsub.Bus) (err error) {
|
||||
// Subscribe to transaction events
|
||||
txch, err := client.Subscribe(ctx, "txevents", "tm.event='Tx'", 100)
|
||||
if err != nil {
|
||||
@@ -289,12 +289,12 @@ func PublishChainTxEvents(ctx context.Context, client cmtclient.EventsClient, bu
|
||||
if !evt.Result.IsOK() {
|
||||
continue
|
||||
}
|
||||
// range over events, parse them using the basic manager and
|
||||
// range over events and parse them
|
||||
// send them to the pubsub bus
|
||||
for _, abciEv := range events {
|
||||
typedEvent, err := sdk.ParseTypedEvent(abciEv)
|
||||
if err != nil {
|
||||
return er
|
||||
return err
|
||||
}
|
||||
if err := bus.Publish(typedEvent); err != nil {
|
||||
bus.Close()
|
||||
|
||||
@@ -264,7 +264,7 @@ type Configurator interface {
|
||||
|
||||
The `ModuleKey` is passed to modules in the `RegisterService` method itself so that `RegisterServices` serves as a single
|
||||
entry point for configuring module services. This is intended to also have the side-effect of greatly reducing boilerplate in
|
||||
`app.go`. For now, `ModuleKey`s will be created based on `AppModuleBasic.Name()`, but a more flexible system may be
|
||||
`app.go`. For now, `ModuleKey`s will be created based on `AppModule.Name()`, but a more flexible system may be
|
||||
introduced in the future. The `ModuleManager` will handle creation of module accounts behind the scenes.
|
||||
|
||||
Because modules do not get direct access to each other anymore, modules may have unfulfilled dependencies. To make sure
|
||||
@@ -344,7 +344,7 @@ Other future improvements may include:
|
||||
* optimizes inter-module calls - for instance caching resolved methods after first invocation
|
||||
* combining `StoreKey`s and `ModuleKey`s into a single interface so that modules have a single OCAPs handle
|
||||
* code generation which makes inter-module communication more performant
|
||||
* decoupling `ModuleKey` creation from `AppModuleBasic.Name()` so that app's can override root module account names
|
||||
* decoupling `ModuleKey` creation from `AppModule.Name()` so that app's can override root module account names
|
||||
* inter-module hooks and plugins
|
||||
|
||||
## Alternatives
|
||||
|
||||
@@ -463,10 +463,10 @@ module manager and follow the Cosmos SDK's existing [0-based versioning](https:/
|
||||
versioning as well as runtime modularity, new officially supported runtime modules will be created under the
|
||||
`cosmossdk.io/runtime` prefix. For each supported consensus engine a semantically-versioned go module should be created
|
||||
with a runtime implementation for that consensus engine. For example:
|
||||
- `cosmossdk.io/runtime/comet`
|
||||
- `cosmossdk.io/runtime/comet/v2`
|
||||
- `cosmossdk.io/runtime/rollkit`
|
||||
- etc.
|
||||
* `cosmossdk.io/runtime/comet`
|
||||
* `cosmossdk.io/runtime/comet/v2`
|
||||
* `cosmossdk.io/runtime/rollkit`
|
||||
* etc.
|
||||
|
||||
These runtime modules should attempt to be semantically versioned even if the underlying consensus engine is not. Also,
|
||||
because a runtime module is also a first class Cosmos SDK module, it should have a protobuf module config type.
|
||||
|
||||
+29
-58
@@ -27,15 +27,13 @@ For legacy reason modules can still implement interfaces from the SDK `module` p
|
||||
There are 2 main application module interfaces:
|
||||
|
||||
* [`appmodule.AppModule` / `module.AppModule`](#appmodule) for inter-dependent module functionalities (except genesis-related functionalities).
|
||||
* (legacy) [`module.AppModuleBasic`](#appmodulebasic) for independent module functionalities. New modules can use `module.CoreAppModuleBasicAdaptor` instead.
|
||||
|
||||
The above interfaces are mostly embedding smaller interfaces (extension interfaces), that defines specific functionalities:
|
||||
|
||||
* (legacy) `module.HasName`: Allows the module to provide its own name for legacy purposes.
|
||||
* (legacy) [`module.HasGenesisBasics`](#modulehasgenesisbasics): The legacy interface for stateless genesis methods.
|
||||
* [`module.HasGenesis`](#modulehasgenesis) for inter-dependent genesis-related module functionalities.
|
||||
* [`module.HasABCIGenesis`](#modulehasabcigenesis) for inter-dependent genesis-related module functionalities.
|
||||
* [`appmodule.HasGenesis` / `module.HasGenesis`](#appmodulehasgenesis): The extension interface for stateful genesis methods.
|
||||
* (legacy) [`module.HasGenesis`](#modulehasgenesis) for inter-dependent genesis-related module functionalities.
|
||||
* (legacy) [`module.HasABCIGenesis`](#modulehasabcigenesis) for inter-dependent genesis-related module functionalities.
|
||||
* [`appmodule.HasPreBlocker`](#haspreblocker): The extension interface that contains information about the `AppModule` and `PreBlock`.
|
||||
* [`appmodule.HasBeginBlocker`](#hasbeginblocker): The extension interface that contains information about the `AppModule` and `BeginBlock`.
|
||||
* [`appmodule.HasEndBlocker`](#hasendblocker): The extension interface that contains information about the `AppModule` and `EndBlock`.
|
||||
@@ -46,31 +44,34 @@ The above interfaces are mostly embedding smaller interfaces (extension interfac
|
||||
* (legacy) [`module.HasInvariants`](#hasinvariants): The extension interface for registering invariants.
|
||||
* (legacy) [`module.HasConsensusVersion`](#hasconsensusversion): The extension interface for declaring a module consensus version.
|
||||
|
||||
The `AppModuleBasic` interface exists to define independent methods of the module, i.e. those that do not depend on other modules in the application. This allows for the construction of the basic application structure early in the application definition, generally in the `init()` function of the [main application file](https://docs.cosmos.network/main/learn/beginner/app-anatomy).
|
||||
|
||||
The `AppModule` interface exists to define inter-dependent module methods. Many modules need to interact with other modules, typically through [`keeper`s](./06-keeper.md), which means there is a need for an interface where modules list their `keeper`s and other methods that require a reference to another module's object. `AppModule` interface extension, such as `HasBeginBlocker` and `HasEndBlocker`, also enables the module manager to set the order of execution between module's methods like `BeginBlock` and `EndBlock`, which is important in cases where the order of execution between modules matters in the context of the application.
|
||||
|
||||
The usage of extension interfaces allows modules to define only the functionalities they need. For example, a module that does not need an `EndBlock` does not need to define the `HasEndBlocker` interface and thus the `EndBlock` method. `AppModule` and `AppModuleGenesis` are voluntarily small interfaces, that can take advantage of the `Module` patterns without having to define many placeholder functions.
|
||||
|
||||
### `AppModuleBasic`
|
||||
|
||||
:::note
|
||||
Use `module.CoreAppModuleBasicAdaptor` instead for creating an `AppModuleBasic` from an `appmodule.AppModule`.
|
||||
:::
|
||||
|
||||
The `AppModuleBasic` interface defines the independent methods modules need to implement.
|
||||
### `HasAminoCodec`
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go#L56-L66
|
||||
// TODO
|
||||
```
|
||||
|
||||
Let us go through the methods:
|
||||
|
||||
* `RegisterLegacyAminoCodec(*codec.LegacyAmino)`: Registers the `amino` codec for the module, which is used to marshal and unmarshal structs to/from `[]byte` in order to persist them in the module's `KVStore`.
|
||||
|
||||
### `HasRegisterInterfaces`
|
||||
|
||||
```go reference
|
||||
// TODO
|
||||
```
|
||||
|
||||
* `RegisterInterfaces(codectypes.InterfaceRegistry)`: Registers a module's interface types and their concrete implementations as `proto.Message`.
|
||||
|
||||
### `HasGRPCGateway`
|
||||
|
||||
```go reference
|
||||
// TODO
|
||||
```
|
||||
|
||||
* `RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)`: Registers gRPC routes for the module.
|
||||
|
||||
All the `AppModuleBasic` of an application are managed by the [`BasicManager`](#basicmanager).
|
||||
|
||||
### `HasName`
|
||||
|
||||
@@ -83,7 +84,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go
|
||||
### Genesis
|
||||
|
||||
:::tip
|
||||
For easily creating an `AppModule` that only has genesis functionalities, use `module.GenesisOnlyAppModule`.
|
||||
For easily creating an `AppModule` that only has genesis functionalities, implement `module.HasGenesis/HasABCIGenesis` and `module.HasName`.
|
||||
:::
|
||||
|
||||
#### `module.HasGenesisBasics`
|
||||
@@ -113,16 +114,6 @@ https://github.com/cosmos/cosmos-sdk/blob/6ce2505/types/module/module.go#L184-L1
|
||||
https://github.com/cosmos/cosmos-sdk/blob/6ce2505/types/module/module.go#L191-L196
|
||||
```
|
||||
|
||||
#### `appmodule.HasGenesis`
|
||||
|
||||
:::warning
|
||||
`appmodule.HasGenesis` is experimental and should be considered unstable, it is recommended to not use this interface at this time.
|
||||
:::
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/6ce2505/core/appmodule/genesis.go#L8-L25
|
||||
```
|
||||
|
||||
### `AppModule`
|
||||
|
||||
The `AppModule` interface defines a module. Modules can declare their functionalities by implementing extensions interfaces.
|
||||
@@ -238,49 +229,24 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/core/appmodule/module.
|
||||
|
||||
### Implementing the Application Module Interfaces
|
||||
|
||||
// TODO reword!
|
||||
|
||||
Typically, the various application module interfaces are implemented in a file called `module.go`, located in the module's folder (e.g. `./x/module/module.go`).
|
||||
|
||||
Almost every module needs to implement the `AppModuleBasic` and `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./06-keeper.md) as a parameter.
|
||||
Almost every module needs to implement the `AppModule` interfaces. If the module is only used for genesis, it will implement `AppModuleGenesis` instead of `AppModule`. The concrete type that implements the interface can add parameters that are required for the implementation of the various methods of the interface. For example, the `Route()` function often calls a `NewMsgServerImpl(k keeper)` function defined in `keeper/msg_server.go` and therefore needs to pass the module's [`keeper`](./06-keeper.md) as a parameter.
|
||||
|
||||
```go
|
||||
// example
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
keeper Keeper
|
||||
}
|
||||
```
|
||||
|
||||
In the example above, you can see that the `AppModule` concrete type references an `AppModuleBasic`, and not an `AppModuleGenesis`. That is because `AppModuleGenesis` only needs to be implemented in modules that focus on genesis-related functionalities. In most modules, the concrete `AppModule` type will have a reference to an `AppModuleBasic` and implement the two added methods of `AppModuleGenesis` directly in the `AppModule` type.
|
||||
|
||||
If no parameter is required (which is often the case for `AppModuleBasic`), just declare an empty concrete type like so:
|
||||
## Module Manager
|
||||
|
||||
```go
|
||||
type AppModuleBasic struct{}
|
||||
```
|
||||
|
||||
## Module Managers
|
||||
|
||||
Module managers are used to manage collections of `AppModuleBasic` and `AppModule`.
|
||||
|
||||
### `BasicManager`
|
||||
|
||||
The `BasicManager` is a structure that lists all the `AppModuleBasic` of an application:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/types/module/module.go#L82
|
||||
```
|
||||
|
||||
It implements the following methods:
|
||||
|
||||
* `NewBasicManager(modules ...AppModuleBasic)`: Constructor function. It takes a list of the application's `AppModuleBasic` and builds a new `BasicManager`. This function is generally called in the `init()` function of [`app.go`](../../learn/beginner/00-app-anatomy.md#core-application-file) to quickly initialize the independent elements of the application's modules (click [here](https://github.com/cosmos/gaia/blob/main/app/app.go#L59-L74) to see an example).
|
||||
* `NewBasicManagerFromManager(manager *Manager, customModuleBasics map[string]AppModuleBasic)`: Constructor function. It creates a new `BasicManager` from a `Manager`. The `BasicManager` will contain all `AppModuleBasic` from the `AppModule` manager using `CoreAppModuleBasicAdaptor` whenever possible. Module's `AppModuleBasic` can be overridden by passing a custom AppModuleBasic map
|
||||
* `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../../learn/advanced/05-encoding.md#amino) of each of the application's `AppModuleBasic`. This function is usually called early on in the [application's construction](../../learn/beginner/00-app-anatomy.md#constructor).
|
||||
* `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModuleBasic`.
|
||||
* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It only calls the modules that implements the `HasGenesisBasics` interfaces.
|
||||
* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of modules implementing the `HasGenesisBasics` interface.
|
||||
* `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules.
|
||||
* `AddTxCommands(rootTxCmd *cobra.Command)`: Adds modules' transaction commands (defined as `GetTxCmd() *cobra.Command`) to the application's [`rootTxCommand`](../../learn/advanced/07-cli.md#transaction-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../../learn/advanced/07-cli.md).
|
||||
* `AddQueryCommands(rootQueryCmd *cobra.Command)`: Adds modules' query commands (defined as `GetQueryCmd() *cobra.Command`) to the application's [`rootQueryCommand`](../../learn/advanced/07-cli.md#query-commands). This function is usually called function from the `main.go` function of the [application's command-line interface](../../learn/advanced/07-cli.md).
|
||||
The module manager is used to manage collections of `appmodule.AppModule` and `AppModule` and all the extensions interfaces.
|
||||
|
||||
### `Manager`
|
||||
|
||||
@@ -312,6 +278,11 @@ The module manager is used throughout the application whenever an action on a co
|
||||
* `EndBlock(context.Context) ([]abci.ValidatorUpdate, error)`: At the end of each block, this function is called from [`BaseApp`](../../learn/advanced/00-baseapp.md#endblock) and, in turn, calls the [`EndBlock`](./06-beginblock-endblock.md) function of each modules implementing the `module.HasABCIEndBlock` interface, in the order defined in `OrderEndBlockers`. It creates a child [context](../../learn/advanced/02-context.md) with an event manager to aggregate [events](../../learn/advanced/08-events.md) emitted from all modules. The function returns an `abci` which contains the aforementioned events, as well as validator set updates (if any).
|
||||
* `Precommit(ctx context.Context)`: During [`Commit`](../../learn/advanced/00-baseapp.md#commit), this function is called from `BaseApp` immediately before the [`deliverState`](../../learn/advanced/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../learn/advanced/04-store.md#commitmultistore) and, in turn calls the `Precommit` function of each modules implementing the `HasPrecommit` interface, in the order defined in `OrderPrecommiters`. It creates a child [context](../../learn/advanced/02-context.md) where the underlying `CacheMultiStore` is that of the newly committed block's [`finalizeblockstate`](../../learn/advanced/00-baseapp.md#state-updates).
|
||||
* `PrepareCheckState(ctx context.Context)`: During [`Commit`](../../learn/advanced/00-baseapp.md#commit), this function is called from `BaseApp` immediately after the [`deliverState`](../../learn/advanced/00-baseapp.md#state-updates) is written to the underlying [`rootMultiStore`](../../learn/advanced/04-store.md#commitmultistore) and, in turn calls the `PrepareCheckState` function of each module implementing the `HasPrepareCheckState` interface, in the order defined in `OrderPrepareCheckStaters`. It creates a child [context](../../learn/advanced/02-context.md) where the underlying `CacheMultiStore` is that of the next block's [`checkState`](../../learn/advanced/00-baseapp.md#state-updates). Writes to this state will be present in the [`checkState`](../../learn/advanced/00-baseapp.md#state-updates) of the next block, and therefore this method can be used to prepare the `checkState` for the next block.
|
||||
* (Optional) `RegisterLegacyAminoCodec(cdc *codec.LegacyAmino)`: Registers the [`codec.LegacyAmino`s](../../learn/advanced/05-encoding.md#amino) of each of the application module. This function is usually called early on in the [application's construction](../../learn/beginner/00-app-anatomy.md#constructor).
|
||||
* `RegisterInterfaces(registry codectypes.InterfaceRegistry)`: Registers interface types and implementations of each of the application's `AppModule`.
|
||||
* (Optional) `RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux)`: Registers gRPC routes for modules.
|
||||
* `DefaultGenesis(cdc codec.JSONCodec)`: Provides default genesis information for modules in the application by calling the [`DefaultGenesis(cdc codec.JSONCodec)`](./08-genesis.md#defaultgenesis) function of each module. It only calls the modules that implements the `HasGenesisBasics` interfaces.
|
||||
* `ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage)`: Validates the genesis information modules by calling the [`ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage)`](./08-genesis.md#validategenesis) function of modules implementing the `HasGenesisBasics` interface.
|
||||
|
||||
Here's an example of a concrete integration within an `simapp`:
|
||||
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ The Cosmos SDK uses Protobuf definitions to generate client and server code:
|
||||
|
||||
A `RegisterMsgServer` method is also generated and should be used to register the module's `MsgServer` implementation in `RegisterServices` method from the [`AppModule` interface](./01-module-manager.md#appmodule).
|
||||
|
||||
In order for clients (CLI and grpc-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](01-module-manager.md#appmodulebasic) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument.
|
||||
In order for clients (CLI and grpc-gateway) to have these URLs registered, the Cosmos SDK provides the function `RegisterMsgServiceDesc(registry codectypes.InterfaceRegistry, sd *grpc.ServiceDesc)` that should be called inside module's [`RegisterInterfaces`](01-module-manager.md#hasregisterinterfaces) method, using the proto-generated `&_Msg_serviceDesc` as `*grpc.ServiceDesc` argument.
|
||||
|
||||
|
||||
## Queries
|
||||
|
||||
+1
-72
@@ -64,84 +64,13 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/bank/module.go#L84-L
|
||||
This section is being rewritten. Refer to [AutoCLI](https://docs.cosmos.network/main/core/autocli) while this section is being updated.
|
||||
:::
|
||||
|
||||
<!-- UPDATE THIS TO AUTOCLI
|
||||
[Queries](./02-messages-and-queries.md#queries) allow users to gather information about the application or network state; they are routed by the application and processed by the module in which they are defined. Query commands typically have their own `query.go` file in the module's `./client/cli` folder. Like transaction commands, they are specified in getter functions. Here is an example of a query command from the `x/auth` module:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/client/cli/query.go#L86-L128
|
||||
```
|
||||
|
||||
In the example, `GetAccountCmd()` creates and returns a query command that returns the state of an account based on the provided account address.
|
||||
|
||||
In general, the getter function does the following:
|
||||
|
||||
* **Constructs the command:** Read the [Cobra Documentation](https://pkg.go.dev/github.com/spf13/cobra) for more detailed information on how to create commands.
|
||||
* **Use:** Specifies the format of the user input required to invoke the command. In the example above, `account` is the name of the query command and `[address]` is the argument.
|
||||
* **Args:** The number of arguments the user provides. In this case, there is exactly one: `[address]`.
|
||||
* **Short and Long:** Descriptions for the command. A `Short` description is expected. A `Long` description can be used to provide additional information that is displayed when a user adds the `--help` flag.
|
||||
* **RunE:** Defines a function that can return an error. This is the function that is called when the command is executed. This function encapsulates all of the logic to create a new query.
|
||||
* The function typically starts by getting the `clientCtx`, which can be done with `client.GetClientQueryContext(cmd)`. The `clientCtx` contains information relevant to query handling.
|
||||
* If applicable, the command's arguments are parsed. In this example, the argument `[address]` is parsed.
|
||||
* A new `queryClient` is initialized using `NewQueryClient(clientCtx)`. The `queryClient` is then used to call the appropriate [query](./02-messages-and-queries.md#grpc-queries).
|
||||
* The `clientCtx.PrintProto` method is used to format the `proto.Message` object so that the results can be printed back to the user.
|
||||
* **Adds query flags:** All query commands must add a set of query [flags](#flags). The query flags are added to the constructed command using `AddQueryFlagsToCmd(cmd)`.
|
||||
* **Returns the command:** Finally, the query command is returned.
|
||||
|
||||
Each module must implement `GetQueryCmd()`, which aggregates all of the query commands of the module. Here is an example from the `x/auth` module:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/auth/client/cli/query.go#L33-L53
|
||||
```
|
||||
|
||||
Each module must also implement the `GetQueryCmd()` method for `AppModuleBasic` that returns the `GetQueryCmd()` function. This allows for the root command to easily aggregate all of the query commands for each module. Here is an example:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/bank/module.go#L84-L87
|
||||
```
|
||||
|
||||
### Flags
|
||||
|
||||
[Flags](../../learn/advanced/07-cli.md#flags) allow users to customize commands. `--fees` and `--gas-prices` are examples of flags that allow users to set the [fees](../../learn/beginner/04-gas-fees.md) and gas prices for their transactions.
|
||||
|
||||
Flags that are specific to a module are typically created in a `flags.go` file in the module's `./client/cli` folder. When creating a flag, developers set the value type, the name of the flag, the default value, and a description about the flag. Developers also have the option to mark flags as _required_ so that an error is thrown if the user does not include a value for the flag.
|
||||
|
||||
Here is an example that adds the `--from` flag to a command:
|
||||
|
||||
```go
|
||||
cmd.Flags().String(FlagFrom, "", "Name or address of private key with which to sign")
|
||||
```
|
||||
|
||||
In this example, the value of the flag is a `String`, the name of the flag is `from` (the value of the `FlagFrom` constant), the default value of the flag is `""`, and there is a description that will be displayed when a user adds `--help` to the command.
|
||||
|
||||
Here is an example that marks the `--from` flag as _required_:
|
||||
|
||||
```go
|
||||
cmd.MarkFlagRequired(FlagFrom)
|
||||
```
|
||||
|
||||
For more detailed information on creating flags, visit the [Cobra Documentation](https://github.com/spf13/cobra).
|
||||
|
||||
As mentioned in [transaction commands](#transaction-commands), there is a set of flags that all transaction commands must add. This is done with the `AddTxFlagsToCmd` method defined in the Cosmos SDK's `./client/flags` package.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/client/flags/flags.go#L108-L138
|
||||
```
|
||||
|
||||
Since `AddTxFlagsToCmd(cmd *cobra.Command)` includes all of the basic flags required for a transaction command, module developers may choose not to add any of their own (specifying arguments instead may often be more appropriate).
|
||||
|
||||
Similarly, there is a `AddQueryFlagsToCmd(cmd *cobra.Command)` to add common flags to a module query command.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/client/flags/flags.go#L95-L106```
|
||||
-->
|
||||
|
||||
## gRPC
|
||||
|
||||
[gRPC](https://grpc.io/) is a Remote Procedure Call (RPC) framework. RPC is the preferred way for external clients like wallets and exchanges to interact with a blockchain.
|
||||
|
||||
In addition to providing an ABCI query pathway, the Cosmos SDK provides a gRPC proxy server that routes gRPC query requests to ABCI query requests.
|
||||
|
||||
In order to do that, modules must implement `RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux)` on `AppModuleBasic` to wire the client gRPC requests to the correct handler inside the module.
|
||||
In order to do that, modules must implement the `module.HasGRPCGateway` interface on `AppModule` to wire the client gRPC requests to the correct handler inside the module.
|
||||
|
||||
Here's an example from the `x/auth` module:
|
||||
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ x/{module_name}
|
||||
* `client/`: The module's CLI client functionality implementation and the module's CLI testing suite.
|
||||
* `exported/`: The module's exported types - typically interface types. If a module relies on keepers from another module, it is expected to receive the keepers as interface contracts through the `expected_keepers.go` file (see below) in order to avoid a direct dependency on the module implementing the keepers. However, these interface contracts can define methods that operate on and/or return types that are specific to the module that is implementing the keepers and this is where `exported/` comes into play. The interface types that are defined in `exported/` use canonical types, allowing for the module to receive the keepers as interface contracts through the `expected_keepers.go` file. This pattern allows for code to remain DRY and also alleviates import cycle chaos.
|
||||
* `keeper/`: The module's `Keeper` and `MsgServer` implementation.
|
||||
* `module/`: The module's `AppModule` and `AppModuleBasic` implementation.
|
||||
* `module/`: The module's `AppModule` implementation.
|
||||
* `abci.go`: The module's `BeginBlocker` and `EndBlocker` implementations (this file is only required if `BeginBlocker` and/or `EndBlocker` need to be defined).
|
||||
* `autocli.go`: The module [autocli](https://docs.cosmos.network/main/core/autocli) options.
|
||||
* `simulation/`: The module's [simulation](./14-simulator.md) package defines functions used by the blockchain simulator application (`simapp`).
|
||||
|
||||
@@ -55,7 +55,7 @@ The first thing defined in `app.go` is the `type` of the application. It is gene
|
||||
* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../../build/building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions.
|
||||
* **A reference to an [`appCodec`](../advanced/05-encoding.md).** 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](../advanced/05-encoding.md).
|
||||
* **A reference to a [`legacyAmino`](../advanced/05-encoding.md) 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.
|
||||
* **A reference to a [module manager](../../build/building-modules/01-module-manager.md#manager)** and a [basic module manager](../../build/building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's modules. It facilitates operations related to these modules, like registering their [`Msg` service](../advanced/00-baseapp.md#msg-services) and [gRPC `Query` service](../advanced/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`PreBlocker`](#preblocker) and [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker).
|
||||
* **A reference to a [module manager](../../build/building-modules/01-module-manager.md#manager)**. The module manager is an object that contains a list of the application's modules. It facilitates operations related to these modules, like registering their [`Msg` service](../advanced/00-baseapp.md#msg-services) and [gRPC `Query` service](../advanced/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`PreBlocker`](#preblocker) and [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker).
|
||||
|
||||
See an example of application type definition from `simapp`, the Cosmos SDK's own app used for demo and testing purposes:
|
||||
|
||||
@@ -73,7 +73,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/server/types/app.go#L6
|
||||
|
||||
Here are the main actions performed by this function:
|
||||
|
||||
* Instantiate a new [`codec`](../advanced/05-encoding.md) and initialize the `codec` of each of the application's modules using the [basic manager](../../build/building-modules/01-module-manager.md#basicmanager).
|
||||
* Instantiate a new [`codec`](../advanced/05-encoding.md) and initialize the `codec` of each of the application's modules using the module manager.
|
||||
* Instantiate a new application with a reference to a `baseapp` instance, a codec, and all the appropriate store keys.
|
||||
* Instantiate all the [`keeper`](#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](../../build/building-modules/01-module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules.
|
||||
@@ -165,7 +165,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/params/encoding
|
||||
|
||||
### Application Module Interface
|
||||
|
||||
Modules must implement [interfaces](../../build/building-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK, [`AppModuleBasic`](../../build/building-modules/01-module-manager.md#appmodulebasic) and [`AppModule`](../../build/building-modules/01-module-manager.md#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' `keeper`s). Both the `AppModule` and `AppModuleBasic` types are, by convention, defined in a file called `module.go`.
|
||||
Modules must implement [interfaces](../../build/building-modules/01-module-manager.md#application-module-interfaces) defined in the Cosmos SDK and [`AppModule`](../../build/building-modules/01-module-manager.md#appmodule). `AppModule` handles the bulk of the module methods (including methods that require references to other modules' `keeper`s). `AppModule` is, 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`](../../build/building-modules/01-module-manager.md#manager), which manages the application's collection of modules.
|
||||
|
||||
@@ -235,7 +235,7 @@ Generally, the [commands related to a module](../../build/building-modules/09-mo
|
||||
|
||||
Each module can expose gRPC endpoints called [service methods](https://grpc.io/docs/what-is-grpc/core-concepts/#service-definition), which are defined in the [module's Protobuf `query.proto` file](#grpc-query-services). 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.
|
||||
* (Optional) Define a `RegisterGRPCGatewayRoutes` method on `AppModule` 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
|
||||
|
||||
Reference in New Issue
Block a user