Modules depinject-ready
depinject
is used to wire any module in app.go
.
All core modules are already configured to support dependency injection.
To work with depinject
a module must define its configuration and requirements so that depinject
can provide the right dependencies.
In brief, as a module developer, the following steps are required:
- Define the module configuration using Protobuf
- Define the module dependencies in
x/{moduleName}/module.go
A chain developer can then use the module by following these two steps:
- Configure the module in
app_config.go
orapp.yaml
- Inject the module in
app.go
Module Configuration
The module available configuration is defined in a Protobuf file, located at {moduleName}/module/v1/module.proto
.
loading...
go_import
must point to the Go package of the custom module.Message fields define the module configuration. That configuration can be set in the
app_config.go
/app.yaml
file for a chain developer to configure the module.
Takinggroup
as example, a chain developer is able to decide, thanks touint64 max_metadata_len
, what the maximum metadata length allowed for a group proposal is.simapp/app_config.goloading...
That message is generated using pulsar
(by running make proto-gen
).
In the case of the group
module, this file is generated here: https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/api/cosmos/group/module/v1/module.pulsar.go.
The part that is relevant for the module configuration is:
loading...
Pulsar is optional. The official protoc-gen-go
can be used as well.
Dependency Definition
Once the configuration proto is defined, the module's module.go
must define what dependencies are required by the module.
The boilerplate is similar for all modules.
All methods, structs and their fields must be public for depinject
.
Import the module configuration generated package:
x/group/module/module.goloading...
Define an
init()
function for defining theproviders
of the module configuration:
This registers the module configuration message and the wiring of the module.x/group/module/module.goloading...
Ensure that the module implements the
appmodule.AppModule
interface:x/group/module/module.goloading...
Define a struct that inherits
depinject.In
and define the module inputs (i.e. module dependencies):depinject
provides the right dependencies to the module.depinject
also checks that all dependencies are provided.tipFor making a dependency optional, add the
optional:"true"
struct tag.x/group/module/module.goloading...
Define the module outputs with a public struct that inherits
depinject.Out
: The module outputs are the dependencies that the module provides to other modules. It is usually the module itself and its keeper.x/group/module/module.goloading...
Create a function named
ProvideModule
(as called in 1.) and use the inputs for instantiating the module outputs.x/group/module/module.goloading...
The
ProvideModule
function should return an instance ofcosmossdk.io/core/appmodule.AppModule
which implements one or more app module extension interfaces for initializing the module.Following is the complete app wiring configuration for
group
:x/group/module/module.goloading...
All modules must implement
depinject.OnePerModuleType
interface. This is used in order to tell the dependency injection framework that the module can only be instantiated once.x/group/module/module.goloading...
The module is now ready to be used with depinject
by a chain developer.
Integrate in an application
The App Wiring is done in app_config.go
/ app.yaml
and app_di.go
and is explained in detail in the overview of app_di.go
.