package app import ( "encoding/json" abci "github.com/tendermint/abci/types" cmn "github.com/tendermint/tmlibs/common" dbm "github.com/tendermint/tmlibs/db" "github.com/tendermint/tmlibs/log" bam "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" "github.com/cosmos/cosmos-sdk/x/ibc" "github.com/cosmos/cosmos-sdk/x/simplestake" "github.com/cosmos/cosmos-sdk/examples/basecoin/types" ) const ( appName = "BasecoinApp" ) // Extended ABCI application type BasecoinApp struct { *bam.BaseApp cdc *wire.Codec // keys to access the substores capKeyMainStore *sdk.KVStoreKey capKeyAccountStore *sdk.KVStoreKey capKeyIBCStore *sdk.KVStoreKey capKeyStakingStore *sdk.KVStoreKey // Manage getting and setting accounts accountMapper sdk.AccountMapper // Handle fees feeHandler sdk.FeeHandler } func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { // Create app-level codec for txs and accounts. var cdc = MakeCodec() // Create your application object. var app = &BasecoinApp{ BaseApp: bam.NewBaseApp(appName, logger, db), cdc: cdc, capKeyMainStore: sdk.NewKVStoreKey("main"), capKeyAccountStore: sdk.NewKVStoreKey("acc"), capKeyIBCStore: sdk.NewKVStoreKey("ibc"), capKeyStakingStore: sdk.NewKVStoreKey("stake"), } // Define the accountMapper. app.accountMapper = auth.NewAccountMapper( cdc, app.capKeyMainStore, // target store &types.AppAccount{}, // prototype ).Seal() // Define the feeHandler. app.feeHandler = func(ctx sdk.Context, fees sdk.Coins) {} // Add handlers. coinKeeper := bank.NewCoinKeeper(app.accountMapper) ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) stakeKeeper := simplestake.NewKeeper(app.capKeyStakingStore, coinKeeper) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). AddRoute("simplestake", simplestake.NewHandler(stakeKeeper)) // Initialize BaseApp. app.SetTxDecoder(app.txDecoder) app.SetInitChainer(app.initChainer) app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeyIBCStore, app.capKeyStakingStore) app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeHandler)) err := app.LoadLatestVersion(app.capKeyMainStore) if err != nil { cmn.Exit(err.Error()) } return app } // Custom tx codec func MakeCodec() *wire.Codec { var cdc = wire.NewCodec() // Register Msgs cdc.RegisterInterface((*sdk.Msg)(nil), nil) cdc.RegisterConcrete(bank.SendMsg{}, "basecoin/Send", nil) cdc.RegisterConcrete(bank.IssueMsg{}, "basecoin/Issue", nil) cdc.RegisterConcrete(ibc.IBCTransferMsg{}, "basecoin/IBCTransferMsg", nil) cdc.RegisterConcrete(ibc.IBCReceiveMsg{}, "basecoin/IBCReceiveMsg", nil) cdc.RegisterConcrete(simplestake.BondMsg{}, "basecoin/BondMsg", nil) cdc.RegisterConcrete(simplestake.UnbondMsg{}, "basecoin/UnbondMsg", nil) // Register AppAccount cdc.RegisterInterface((*sdk.Account)(nil), nil) cdc.RegisterConcrete(&types.AppAccount{}, "basecoin/Account", nil) // Register crypto. wire.RegisterCrypto(cdc) return cdc } // Custom logic for transaction decoding func (app *BasecoinApp) txDecoder(txBytes []byte) (sdk.Tx, sdk.Error) { var tx = sdk.StdTx{} if len(txBytes) == 0 { return nil, sdk.ErrTxDecode("txBytes are empty") } // StdTx.Msg is an interface. The concrete types // are registered by MakeTxCodec in bank.RegisterAmino. err := app.cdc.UnmarshalBinary(txBytes, &tx) if err != nil { return nil, sdk.ErrTxDecode("").TraceCause(err, "") } return tx, nil } // Custom logic for basecoin initialization func (app *BasecoinApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { stateJSON := req.AppStateBytes genesisState := new(types.GenesisState) err := json.Unmarshal(stateJSON, genesisState) if err != nil { panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") } for _, gacc := range genesisState.Accounts { acc, err := gacc.ToAppAccount() if err != nil { panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 // return sdk.ErrGenesisParse("").TraceCause(err, "") } app.accountMapper.SetAccount(ctx, acc) } return abci.ResponseInitChain{} }