# app.go

> Loc:cmd/gaia/app/app.go

具体gaiaApp对baseapp的二次封装结构

```go
// Extended ABCI application
type GaiaApp struct {
    *bam.BaseApp
    cdc *wire.Codec

    // keys to access the substores
    keyMain    *sdk.KVStoreKey
    keyAccount *sdk.KVStoreKey
    keyIBC     *sdk.KVStoreKey
    keyStake   *sdk.KVStoreKey

    // Manage getting and setting accounts
    accountMapper sdk.AccountMapper
    coinKeeper    bank.Keeper
    ibcMapper     ibc.Mapper
    stakeKeeper   stake.Keeper
}
```

* `*bam.BaseApp` 这个就是baseapp的基本结构，在他基础上二次开发
* `keyStake   *sdk.KVStoreKey` KVstore的键类型，这是stake的键，如果你想添加自己的module，你可以添加`keyMyModule *sdk.KVStoreKey`
* `stakeKeeper   stake.Keeper` stake.keeper结构(在x/stake/keeper.go里)用来访问和设置kvstore，如果你想要添加自己的module，你可以添加`mymoduleKeeper mymodule.Keeper`

下面就是GaiaApp的构造，完整代码我拆分开来，讲解起来更方便

```go
func NewGaiaApp(logger log.Logger, db dbm.DB) *GaiaApp {
    cdc := MakeCodec()

    // create your application object
    var app = &GaiaApp{
        BaseApp:    bam.NewBaseApp(appName, cdc, logger, db),
        cdc:        cdc,
        keyMain:    sdk.NewKVStoreKey("main"),
        keyAccount: sdk.NewKVStoreKey("acc"),
        keyIBC:     sdk.NewKVStoreKey("ibc"),
        keyStake:   sdk.NewKVStoreKey("stake"),
    }
```

常见应用的对象的时候，如果你想加入你自己的mymodule,你需要像stake模块一样（`keyStake: sdk.NewKVStoreKey("stake")`）添加自己的`keyMymodule: sdk.NewKVStoreKey("mymodule")`这个key后面会在app.MountStoresIAVL中注册这个名字的stores，每个模块都有自己的名字的kvstore，虽然现在他们其实是公用一个kvstore，他的根是`'main'`,例如stake模块的kvstore是`'main':{'stake':{...},'mymodule':{...},...}`

```go
    // add handlers
    app.coinKeeper = bank.NewKeeper(app.accountMapper)
    app.ibcMapper = ibc.NewMapper(app.cdc, app.keyIBC, app.RegisterCodespace(ibc.DefaultCodespace))
    app.stakeKeeper = stake.NewKeeper(app.cdc, app.keyStake, app.coinKeeper, app.RegisterCodespace(stake.DefaultCodespace))
```

上面代码就是注册自己模块的keeper，每个keeper构造的是时候如果你想访问其他模块的kvstore也可以穿入其他模块的keeper，例如stakeKeeper 就传入了app.coinKeeper. 然后我可以模仿stake 添加自己的模块代码如下：

```go
app.mymoduleKeeper = mymodule.NewKeeper(app.cdc, app.mymodule,app.coinKeeper,app.stakeKeeper,app.RegisterCodespace(mymodule.DefaultCodespace))
```

Keeper在`keeper.go`中定义。

```go
    // register message routes
    app.Router().
        AddRoute("bank", bank.NewHandler(app.coinKeeper)).
        AddRoute("ibc", ibc.NewHandler(app.ibcMapper, app.coinKeeper)).
        AddRoute("stake", stake.NewHandler(app.stakeKeeper))
```

接下来上面的代码就是注册自己的handler，模仿stake在`app.Router()...`后面添加`.AddRoute（"mymodule"，mymodule.NewHandler(app.mymoduleKeeper)）`这样就成功注册了自己模块的handler.这个在`handler.go`里面声明定义。

```go
    // initialize BaseApp
    app.SetInitChainer(app.initChainer)
    app.SetEndBlocker(stake.NewEndBlocker(app.stakeKeeper))
    app.MountStoresIAVL(app.keyMain, app.keyAccount, app.keyIBC, app.keyStake)
    app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, stake.FeeHandler))
    err := app.LoadLatestVersion(app.keyMain)
    if err != nil {
        cmn.Exit(err.Error())
    }

    return app
}
```

app.SetEndBlocker注册endblock的handler,上面代码接受的是stake的endblocker，当然你可以定义自己的endblocker模块，但是要注意一个baseapp就一个endblocker接口，所以只能注册一个handler，并不像checktx和delivertx可以通过router来路由选择对应的handler处理。 下面AnteHandler同理 最后app.MountStoresIAVL(中加入 app.keymymodule....)

```go
// custom tx codec
func MakeCodec() *wire.Codec {
    var cdc = wire.NewCodec()
    ibc.RegisterWire(cdc)
    bank.RegisterWire(cdc)
    stake.RegisterWire(cdc)
    auth.RegisterWire(cdc)
    sdk.RegisterWire(cdc)
    wire.RegisterCrypto(cdc)
    return cdc
}
```

这个go-amino序列化的部分，只需要添加自己的模块部分即可mymodule.RegisterWire(cdc) 这个在`wire.go`里面声明定义

> 具体细节 大家可以参考我的 app.go-mymodule 模版,不过这个在本大章的末尾，因为我先要编写handler.go,keeper.go...,然后再把他们注册入app.go


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mikexu.gitbook.io/cosmossdk-in-action/module-create/setup-the-main-app/app.go.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
