Refactor CoinMapper

CoinMapper is now called CoinKeeper to differentiate it from
AccountMapper. A Mapper retrieves things from a store. A Keeper exposes
functionality of coins and maintain invariants.

bank.NewHandler takes a CoinKeeper instead of the entire AccountMapper.
This commit is contained in:
Adrian Brink 2018-02-09 08:43:08 +01:00 committed by Ethan Buchman
parent 51dca8f0a9
commit 8837af66bd
4 changed files with 37 additions and 35 deletions

View File

@ -25,6 +25,6 @@ func (app *BasecoinApp) initRouterHandlers() {
// All handlers must be added here.
// The order matters.
app.router.AddRoute("bank", bank.NewHandler(app.accountMapper))
app.router.AddRoute("bank", bank.NewHandler(bank.NewCoinKeeper(app.accountMapper)))
app.router.AddRoute("sketchy", sketchy.NewHandler())
}

View File

@ -77,6 +77,19 @@ func (am accountMapper) SetAccount(ctx sdk.Context, acc sdk.Account) {
store.Set(addr, bz)
}
//----------------------------------------
// sealedAccountMapper
type sealedAccountMapper struct {
accountMapper
}
// There's no way for external modules to mutate the
// sam.accountMapper.ctx from here, even with reflection.
func (sam sealedAccountMapper) WireCodec() *wire.Codec {
panic("accountMapper is sealed")
}
//----------------------------------------
// misc.
@ -139,16 +152,3 @@ func (am accountMapper) decodeAccount(bz []byte) sdk.Account {
return reflect.ValueOf(accPtr).Elem().Interface().(sdk.Account)
}
}
//----------------------------------------
// sealedAccountMapper
type sealedAccountMapper struct {
accountMapper
}
// There's no way for external modules to mutate the
// sam.accountMapper.ctx from here, even with reflection.
func (sam sealedAccountMapper) WireCodec() *wire.Codec {
panic("accountMapper is sealed")
}

View File

@ -7,37 +7,33 @@ import (
)
// Handle all "bank" type messages.
// NOTE: Technically, NewHandler only needs a CoinMapper
func NewHandler(am sdk.AccountMapper) sdk.Handler {
func NewHandler(ck CoinKeeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
cm := CoinMapper{am}
switch msg := msg.(type) {
case SendMsg:
return handleSendMsg(ctx, cm, msg)
return handleSendMsg(ctx, ck, msg)
case IssueMsg:
return handleIssueMsg(ctx, cm, msg)
return handleIssueMsg(ctx, ck, msg)
default:
errMsg := "Unrecognized bank Msg type: " + reflect.TypeOf(msg).Name()
return sdk.ErrUnknownRequest(errMsg).Result()
}
}
}
// Handle SendMsg.
func handleSendMsg(ctx sdk.Context, cm CoinMapper, msg SendMsg) sdk.Result {
func handleSendMsg(ctx sdk.Context, ck CoinKeeper, msg SendMsg) sdk.Result {
// NOTE: totalIn == totalOut should already have been checked
for _, in := range msg.Inputs {
_, err := cm.SubtractCoins(ctx, in.Address, in.Coins)
_, err := ck.SubtractCoins(ctx, in.Address, in.Coins)
if err != nil {
return err.Result()
}
}
for _, out := range msg.Outputs {
_, err := cm.AddCoins(ctx, out.Address, out.Coins)
_, err := ck.AddCoins(ctx, out.Address, out.Coins)
if err != nil {
return err.Result()
}
@ -47,6 +43,6 @@ func handleSendMsg(ctx sdk.Context, cm CoinMapper, msg SendMsg) sdk.Result {
}
// Handle IssueMsg.
func handleIssueMsg(ctx sdk.Context, cm CoinMapper, msg IssueMsg) sdk.Result {
func handleIssueMsg(ctx sdk.Context, ck CoinKeeper, msg IssueMsg) sdk.Result {
panic("not implemented yet")
}

View File

@ -3,18 +3,24 @@ package bank
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
crypto "github.com/tendermint/go-crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// CoinMapper manages transfers between accounts
type CoinMapper struct {
// CoinKeeper manages transfers between accounts
type CoinKeeper struct {
am sdk.AccountMapper
}
// NewCoinKeeper returns a new CoinKeeper
func NewCoinKeeper(am sdk.AccountMapper) CoinKeeper {
return CoinKeeper{am: am}
}
// SubtractCoins subtracts amt from the coins at the addr.
func (cm CoinMapper) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
acc := cm.am.GetAccount(ctx, addr)
func (ck CoinKeeper) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
acc := ck.am.GetAccount(ctx, addr)
if acc == nil {
return amt, sdk.ErrUnrecognizedAddress(addr)
}
@ -26,21 +32,21 @@ func (cm CoinMapper) SubtractCoins(ctx sdk.Context, addr crypto.Address, amt sdk
}
acc.SetCoins(newCoins)
cm.am.SetAccount(ctx, acc)
ck.am.SetAccount(ctx, acc)
return newCoins, nil
}
// AddCoins adds amt to the coins at the addr.
func (cm CoinMapper) AddCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
acc := cm.am.GetAccount(ctx, addr)
func (ck CoinKeeper) AddCoins(ctx sdk.Context, addr crypto.Address, amt sdk.Coins) (sdk.Coins, sdk.Error) {
acc := ck.am.GetAccount(ctx, addr)
if acc == nil {
acc = cm.am.NewAccountWithAddress(ctx, addr)
acc = ck.am.NewAccountWithAddress(ctx, addr)
}
coins := acc.GetCoins()
newCoins := coins.Plus(amt)
acc.SetCoins(newCoins)
cm.am.SetAccount(ctx, acc)
ck.am.SetAccount(ctx, acc)
return newCoins, nil
}