diff --git a/examples/basecoin/app/app.go b/examples/basecoin/app/app.go index 1d31b0edc4..86860f0465 100644 --- a/examples/basecoin/app/app.go +++ b/examples/basecoin/app/app.go @@ -58,12 +58,12 @@ func NewBasecoinApp(logger log.Logger, db dbm.DB) *BasecoinApp { // add handlers coinKeeper := bank.NewCoinKeeper(app.accountMapper) - coolMapper := cool.NewMapper(app.capKeyMainStore) + coolKeeper := cool.NewKeeper(app.capKeyMainStore, coinKeeper) ibcMapper := ibc.NewIBCMapper(app.cdc, app.capKeyIBCStore) stakingMapper := staking.NewMapper(app.capKeyStakingStore) app.Router(). AddRoute("bank", bank.NewHandler(coinKeeper)). - AddRoute("cool", cool.NewHandler(coinKeeper, coolMapper)). + AddRoute("cool", coolKeeper.Handler). AddRoute("sketchy", sketchy.NewHandler()). AddRoute("ibc", ibc.NewHandler(ibcMapper, coinKeeper)). AddRoute("staking", staking.NewHandler(stakingMapper, coinKeeper)) diff --git a/examples/basecoin/app/app_test.go b/examples/basecoin/app/app_test.go index f97ae30bf6..7168cb2161 100644 --- a/examples/basecoin/app/app_test.go +++ b/examples/basecoin/app/app_test.go @@ -259,12 +259,12 @@ func TestQuizMsg(t *testing.T) { SignCheckDeliver(t, bapp, setTrendMsg1, 0, true) SignCheckDeliver(t, bapp, quizMsg1, 1, true) CheckBalance(t, bapp, "69icecold") - SignCheckDeliver(t, bapp, quizMsg2, 2, true) // result without reward + SignCheckDeliver(t, bapp, quizMsg2, 2, false) // result without reward CheckBalance(t, bapp, "69icecold") SignCheckDeliver(t, bapp, quizMsg1, 3, true) CheckBalance(t, bapp, "138icecold") SignCheckDeliver(t, bapp, setTrendMsg2, 4, true) // reset the trend - SignCheckDeliver(t, bapp, quizMsg1, 5, true) // the same answer will nolonger do! + SignCheckDeliver(t, bapp, quizMsg1, 5, false) // the same answer will nolonger do! CheckBalance(t, bapp, "138icecold") SignCheckDeliver(t, bapp, quizMsg2, 6, true) // earlier answer now relavent again CheckBalance(t, bapp, "69badvibesonly,138icecold") diff --git a/examples/basecoin/x/cool/errors.go b/examples/basecoin/x/cool/errors.go new file mode 100644 index 0000000000..9001c3c243 --- /dev/null +++ b/examples/basecoin/x/cool/errors.go @@ -0,0 +1,15 @@ +package cool + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // Cool module reserves error 300-399 lawl + CodeIncorrectCoolAnswer sdk.CodeType = 300 +) + +// ErrIncorrectCoolAnswer - Error returned upon an incorrect guess +func ErrIncorrectCoolAnswer(answer string) sdk.Error { + return sdk.NewError(CodeIncorrectCoolAnswer, "Incorrect Cool answer - `"+answer+"'") +} diff --git a/examples/basecoin/x/cool/handler.go b/examples/basecoin/x/cool/handler.go index c0aae11bba..fc3dc44ad4 100644 --- a/examples/basecoin/x/cool/handler.go +++ b/examples/basecoin/x/cool/handler.go @@ -5,7 +5,6 @@ import ( "reflect" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank" ) // This is just an example to demonstrate a functional custom module @@ -19,37 +18,42 @@ import ( // \_______/ \______/ \______/ |______/ // Handle all "coolmodule" type objects -func NewHandler(ck bank.CoinKeeper, cm Mapper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - switch msg := msg.(type) { - case SetTrendMsg: - return handleSetTrendMsg(ctx, cm, msg) - case QuizMsg: - return handleQuizMsg(ctx, ck, cm, msg) - default: - errMsg := fmt.Sprintf("Unrecognized cool Msg type: %v", reflect.TypeOf(msg).Name()) - return sdk.ErrUnknownRequest(errMsg).Result() - } +func (k Keeper) Handler(ctx sdk.Context, msg sdk.Msg) sdk.Result { + switch msg := msg.(type) { + case SetTrendMsg: + return handleSetTrendMsg(ctx, k, msg) + case QuizMsg: + return handleQuizMsg(ctx, k, msg) + default: + errMsg := fmt.Sprintf("Unrecognized cool Msg type: %v", reflect.TypeOf(msg).Name()) + return sdk.ErrUnknownRequest(errMsg).Result() } } // Handle QuizMsg This is the engine of your module -func handleSetTrendMsg(ctx sdk.Context, cm Mapper, msg SetTrendMsg) sdk.Result { - cm.SetTrend(ctx, msg.Cool) +func handleSetTrendMsg(ctx sdk.Context, k Keeper, msg SetTrendMsg) sdk.Result { + k.setTrend(ctx, msg.Cool) return sdk.Result{} } // Handle QuizMsg This is the engine of your module -func handleQuizMsg(ctx sdk.Context, ck bank.CoinKeeper, cm Mapper, msg QuizMsg) sdk.Result { +func handleQuizMsg(ctx sdk.Context, k Keeper, msg QuizMsg) sdk.Result { - currentTrend := cm.GetTrend(ctx) + correct := k.CheckTrend(ctx, msg.CoolAnswer) - if msg.CoolAnswer == currentTrend { - bonusCoins := sdk.Coins{{currentTrend, 69}} - _, err := ck.AddCoins(ctx, msg.Sender, bonusCoins) - if err != nil { - return err.Result() - } + if !correct { + return ErrIncorrectCoolAnswer(msg.CoolAnswer).Result() + } + + if ctx.IsCheckTx() { + return sdk.Result{} // TODO + } + + bonusCoins := sdk.Coins{{msg.CoolAnswer, 69}} + + _, err := k.ck.AddCoins(ctx, msg.Sender, bonusCoins) + if err != nil { + return err.Result() } return sdk.Result{} diff --git a/examples/basecoin/x/cool/keeper.go b/examples/basecoin/x/cool/keeper.go new file mode 100644 index 0000000000..e1fbe8f587 --- /dev/null +++ b/examples/basecoin/x/cool/keeper.go @@ -0,0 +1,42 @@ +package cool + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank" +) + +// Keeper - handlers sets/gets of custom variables for your module +type Keeper struct { + ck bank.CoinKeeper + + storeKey sdk.StoreKey // The (unexposed) key used to access the store from the Context. +} + +// NewKeeper - Returns the Keeper +func NewKeeper(key sdk.StoreKey, bankKeeper bank.CoinKeeper) Keeper { + return Keeper{bankKeeper, key} +} + +// Key to knowing the trend on the streets! +var trendKey = []byte("TrendKey") + +// GetTrend - returns the current cool trend +func (k Keeper) GetTrend(ctx sdk.Context) string { + store := ctx.KVStore(k.storeKey) + bz := store.Get(trendKey) + return string(bz) +} + +// Implements sdk.AccountMapper. +func (k Keeper) setTrend(ctx sdk.Context, newTrend string) { + store := ctx.KVStore(k.storeKey) + store.Set(trendKey, []byte(newTrend)) +} + +// CheckTrend - Returns true or false based on whether guessedTrend is currently cool or not +func (k Keeper) CheckTrend(ctx sdk.Context, guessedTrend string) bool { + if guessedTrend == k.GetTrend(ctx) { + return true + } + return false +} diff --git a/examples/basecoin/x/cool/mapper.go b/examples/basecoin/x/cool/mapper.go deleted file mode 100644 index 2e0a791fa6..0000000000 --- a/examples/basecoin/x/cool/mapper.go +++ /dev/null @@ -1,30 +0,0 @@ -package cool - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// This Cool Mapper handlers sets/gets of custom variables for your module -type Mapper struct { - key sdk.StoreKey // The (unexposed) key used to access the store from the Context. -} - -func NewMapper(key sdk.StoreKey) Mapper { - return Mapper{key} -} - -// Key to knowing the trend on the streets! -var trendKey = []byte("TrendKey") - -// Implements sdk.AccountMapper. -func (am Mapper) GetTrend(ctx sdk.Context) string { - store := ctx.KVStore(am.key) - bz := store.Get(trendKey) - return string(bz) -} - -// Implements sdk.AccountMapper. -func (am Mapper) SetTrend(ctx sdk.Context, newTrend string) { - store := ctx.KVStore(am.key) - store.Set(trendKey, []byte(newTrend)) -} diff --git a/x/bank/mapper.go b/x/bank/keeper.go similarity index 76% rename from x/bank/mapper.go rename to x/bank/keeper.go index 0530967f12..919867c65d 100644 --- a/x/bank/mapper.go +++ b/x/bank/keeper.go @@ -6,6 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +const moduleName = "bank" + // CoinKeeper manages transfers between accounts type CoinKeeper struct { am sdk.AccountMapper @@ -48,3 +50,18 @@ func (ck CoinKeeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) ck.am.SetAccount(ctx, acc) return newCoins, nil } + +// SendCoins moves coins from one account to another +func (ck CoinKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) sdk.Error { + _, err := ck.SubtractCoins(ctx, fromAddr, amt) + if err != nil { + return err + } + + _, err = ck.AddCoins(ctx, toAddr, amt) + if err != nil { + return err + } + + return nil +}