cosmos-sdk/x/bank/keeper.go

209 lines
6.8 KiB
Go
Raw Normal View History

package bank
import (
2018-03-24 17:12:44 -07:00
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
)
2018-04-18 21:49:24 -07:00
// Keeper manages transfers between accounts
type Keeper struct {
2018-04-09 15:10:58 -07:00
am sdk.AccountMapper
}
2018-04-18 21:49:24 -07:00
// NewKeeper returns a new Keeper
func NewKeeper(am sdk.AccountMapper) Keeper {
return Keeper{am: am}
2018-04-09 15:10:58 -07:00
}
// GetCoins returns the coins at the addr.
2018-05-07 11:28:53 -07:00
func (keeper Keeper) GetCoins(ctx sdk.Context, addr sdk.Address) (sdk.Coins, sdk.Error) {
2018-04-09 15:10:58 -07:00
return getCoins(ctx, keeper.am, addr)
}
// SetCoins sets the coins at the addr.
2018-04-18 21:49:24 -07:00
func (keeper Keeper) SetCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) sdk.Error {
2018-04-09 15:10:58 -07:00
return setCoins(ctx, keeper.am, addr, amt)
}
// HasCoins returns whether or not an account has at least amt coins.
2018-05-07 11:28:53 -07:00
func (keeper Keeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (bool, sdk.Error) {
2018-04-09 15:10:58 -07:00
return hasCoins(ctx, keeper.am, addr, amt)
}
// SubtractCoins subtracts amt from the coins at the addr.
func (keeper Keeper) SubtractCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return subtractCoins(ctx, keeper.am, addr, amt)
}
// AddCoins adds amt to the coins at the addr.
func (keeper Keeper) AddCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return addCoins(ctx, keeper.am, addr, amt)
}
// SendCoins moves coins from one account to another
func (keeper Keeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper Keeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
}
2018-04-18 21:49:24 -07:00
//______________________________________________________________________________________________
2018-04-09 15:10:58 -07:00
// SendKeeper only allows transfers between accounts, without the possibility of creating coins
type SendKeeper struct {
am sdk.AccountMapper
}
2018-04-18 21:49:24 -07:00
// NewSendKeeper returns a new Keeper
2018-04-09 15:10:58 -07:00
func NewSendKeeper(am sdk.AccountMapper) SendKeeper {
return SendKeeper{am: am}
}
// GetCoins returns the coins at the addr.
2018-05-07 11:28:53 -07:00
func (keeper SendKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) (sdk.Coins, sdk.Error) {
2018-04-09 15:10:58 -07:00
return getCoins(ctx, keeper.am, addr)
}
// HasCoins returns whether or not an account has at least amt coins.
2018-05-07 11:28:53 -07:00
func (keeper SendKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (bool, sdk.Error) {
2018-04-09 15:10:58 -07:00
return hasCoins(ctx, keeper.am, addr, amt)
}
// SendCoins moves coins from one account to another
func (keeper SendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return sendCoins(ctx, keeper.am, fromAddr, toAddr, amt)
}
// InputOutputCoins handles a list of inputs and outputs
func (keeper SendKeeper) InputOutputCoins(ctx sdk.Context, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
2018-04-09 15:10:58 -07:00
return inputOutputCoins(ctx, keeper.am, inputs, outputs)
}
2018-04-18 21:49:24 -07:00
//______________________________________________________________________________________________
2018-04-09 15:10:58 -07:00
// ViewKeeper only allows reading of balances
type ViewKeeper struct {
am sdk.AccountMapper
}
2018-04-18 21:49:24 -07:00
// NewViewKeeper returns a new Keeper
2018-04-09 15:10:58 -07:00
func NewViewKeeper(am sdk.AccountMapper) ViewKeeper {
return ViewKeeper{am: am}
}
// GetCoins returns the coins at the addr.
2018-05-07 11:28:53 -07:00
func (keeper ViewKeeper) GetCoins(ctx sdk.Context, addr sdk.Address) (sdk.Coins, sdk.Error) {
2018-04-09 15:10:58 -07:00
return getCoins(ctx, keeper.am, addr)
}
// HasCoins returns whether or not an account has at least amt coins.
2018-05-07 11:28:53 -07:00
func (keeper ViewKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coins) (bool, sdk.Error) {
2018-04-09 15:10:58 -07:00
return hasCoins(ctx, keeper.am, addr, amt)
}
2018-04-18 21:49:24 -07:00
//______________________________________________________________________________________________
2018-05-07 11:28:53 -07:00
func getCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address) (sdk.Coins, sdk.Error) {
if ctx.GasMeter().ConsumeGasOrFail(10) {
return sdk.Coins{}, sdk.ErrOutOfGas("out of gas in getCoins")
}
2018-04-18 21:49:24 -07:00
acc := am.GetAccount(ctx, addr)
if acc == nil {
2018-05-07 11:28:53 -07:00
return sdk.Coins{}, nil
2018-04-18 21:49:24 -07:00
}
2018-05-07 11:28:53 -07:00
return acc.GetCoins(), nil
2018-04-18 21:49:24 -07:00
}
func setCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) sdk.Error {
2018-05-07 11:40:33 -07:00
if ctx.GasMeter().ConsumeGasOrFail(100) {
return sdk.ErrOutOfGas("out of gas in setCoins")
}
2018-04-18 21:49:24 -07:00
acc := am.GetAccount(ctx, addr)
if acc == nil {
acc = am.NewAccountWithAddress(ctx, addr)
}
acc.SetCoins(amt)
am.SetAccount(ctx, acc)
return nil
}
// HasCoins returns whether or not an account has at least amt coins.
2018-05-07 11:28:53 -07:00
func hasCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (bool, sdk.Error) {
if ctx.GasMeter().ConsumeGasOrFail(10) {
return false, sdk.ErrOutOfGas("out of gas in hasCoins")
}
coins, err := getCoins(ctx, am, addr)
if err != nil {
return false, err
}
return coins.IsGTE(amt), nil
2018-04-18 21:49:24 -07:00
}
// SubtractCoins subtracts amt from the coins at the addr.
func subtractCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
2018-04-18 21:49:24 -07:00
oldCoins := getCoins(ctx, am, addr)
newCoins := oldCoins.Minus(amt)
if !newCoins.IsNotNegative() {
return amt, nil, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
2018-04-18 21:49:24 -07:00
}
err := setCoins(ctx, am, addr, newCoins)
2018-05-09 15:47:28 -07:00
tags := sdk.NewTags("sender", addr.Bytes())
return newCoins, tags, err
2018-04-18 21:49:24 -07:00
}
// AddCoins adds amt to the coins at the addr.
func addCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address, amt sdk.Coins) (sdk.Coins, sdk.Tags, sdk.Error) {
2018-04-18 21:49:24 -07:00
oldCoins := getCoins(ctx, am, addr)
newCoins := oldCoins.Plus(amt)
if !newCoins.IsNotNegative() {
return amt, nil, sdk.ErrInsufficientCoins(fmt.Sprintf("%s < %s", oldCoins, amt))
2018-04-18 21:49:24 -07:00
}
err := setCoins(ctx, am, addr, newCoins)
2018-05-09 15:47:28 -07:00
tags := sdk.NewTags("recipient", addr.Bytes())
return newCoins, tags, err
2018-04-18 21:49:24 -07:00
}
// SendCoins moves coins from one account to another
// NOTE: Make sure to revert state changes from tx on error
func sendCoins(ctx sdk.Context, am sdk.AccountMapper, fromAddr sdk.Address, toAddr sdk.Address, amt sdk.Coins) (sdk.Tags, sdk.Error) {
_, subTags, err := subtractCoins(ctx, am, fromAddr, amt)
2018-04-18 21:49:24 -07:00
if err != nil {
return nil, err
2018-04-18 21:49:24 -07:00
}
_, addTags, err := addCoins(ctx, am, toAddr, amt)
2018-04-18 21:49:24 -07:00
if err != nil {
return nil, err
2018-04-18 21:49:24 -07:00
}
2018-05-10 08:14:46 -07:00
return subTags.AppendTags(addTags), nil
2018-04-18 21:49:24 -07:00
}
// InputOutputCoins handles a list of inputs and outputs
// NOTE: Make sure to revert state changes from tx on error
func inputOutputCoins(ctx sdk.Context, am sdk.AccountMapper, inputs []Input, outputs []Output) (sdk.Tags, sdk.Error) {
allTags := sdk.EmptyTags()
2018-04-18 21:49:24 -07:00
for _, in := range inputs {
_, tags, err := subtractCoins(ctx, am, in.Address, in.Coins)
2018-04-18 21:49:24 -07:00
if err != nil {
return nil, err
2018-04-18 21:49:24 -07:00
}
2018-05-10 08:14:46 -07:00
allTags = allTags.AppendTags(tags)
2018-04-18 21:49:24 -07:00
}
for _, out := range outputs {
_, tags, err := addCoins(ctx, am, out.Address, out.Coins)
2018-04-18 21:49:24 -07:00
if err != nil {
return nil, err
2018-04-18 21:49:24 -07:00
}
2018-05-10 08:14:46 -07:00
allTags = allTags.AppendTags(tags)
2018-04-18 21:49:24 -07:00
}
return allTags, nil
2018-04-18 21:49:24 -07:00
}