feat(bank/v2): Send function (#21606)
This commit is contained in:
parent
bf817f89aa
commit
a77a92adf1
@ -1,12 +1,20 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/collections/indexes"
|
||||
"cosmossdk.io/core/address"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/event"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/x/bank/v2/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
|
||||
// Keeper defines the bank/v2 module keeper.
|
||||
@ -18,6 +26,8 @@ type Keeper struct {
|
||||
addressCodec address.Codec
|
||||
schema collections.Schema
|
||||
params collections.Item[types.Params]
|
||||
balances *collections.IndexedMap[collections.Pair[[]byte, string], math.Int, BalancesIndexes]
|
||||
supply collections.Map[string, math.Int]
|
||||
}
|
||||
|
||||
func NewKeeper(authority []byte, addressCodec address.Codec, env appmodulev2.Environment, cdc codec.BinaryCodec) *Keeper {
|
||||
@ -28,6 +38,8 @@ func NewKeeper(authority []byte, addressCodec address.Codec, env appmodulev2.Env
|
||||
authority: authority,
|
||||
addressCodec: addressCodec, // TODO(@julienrbrt): Should we add address codec to the environment?
|
||||
params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[types.Params](cdc)),
|
||||
balances: collections.NewIndexedMap(sb, types.BalancesPrefix, "balances", collections.PairKeyCodec(collections.BytesKey, collections.StringKey), sdk.IntValue, newBalancesIndexes(sb)),
|
||||
supply: collections.NewMap(sb, types.SupplyKey, "supply", collections.StringKey, sdk.IntValue),
|
||||
}
|
||||
|
||||
schema, err := sb.Build()
|
||||
@ -38,3 +50,205 @@ func NewKeeper(authority []byte, addressCodec address.Codec, env appmodulev2.Env
|
||||
|
||||
return k
|
||||
}
|
||||
|
||||
// MintCoins creates new coins from thin air and adds it to the module account.
|
||||
// An error is returned if the module account does not exist or is unauthorized.
|
||||
func (k Keeper) MintCoins(ctx context.Context, addr []byte, amounts sdk.Coins) error {
|
||||
// TODO: Mint restriction & permission
|
||||
|
||||
if !amounts.IsValid() {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amounts.String())
|
||||
}
|
||||
|
||||
err := k.addCoins(ctx, addr, amounts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, amount := range amounts {
|
||||
supply := k.GetSupply(ctx, amount.GetDenom())
|
||||
supply = supply.Add(amount)
|
||||
k.setSupply(ctx, supply)
|
||||
}
|
||||
|
||||
addrStr, err := k.addressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// emit mint event
|
||||
return k.EventService.EventManager(ctx).EmitKV(
|
||||
types.EventTypeCoinMint,
|
||||
event.NewAttribute(types.AttributeKeyMinter, addrStr),
|
||||
event.NewAttribute(sdk.AttributeKeyAmount, amounts.String()),
|
||||
)
|
||||
}
|
||||
|
||||
// SendCoins transfers amt coins from a sending account to a receiving account.
|
||||
// Function take sender & receipient as []byte.
|
||||
// They can be sdk address or module name.
|
||||
// An error is returned upon failure.
|
||||
func (k Keeper) SendCoins(ctx context.Context, from, to []byte, amt sdk.Coins) error {
|
||||
if !amt.IsValid() {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, amt.String())
|
||||
}
|
||||
|
||||
var err error
|
||||
// TODO: Send restriction
|
||||
|
||||
err = k.subUnlockedCoins(ctx, from, amt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.addCoins(ctx, to, amt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fromAddrString, err := k.addressCodec.BytesToString(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
toAddrString, err := k.addressCodec.BytesToString(to)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return k.EventService.EventManager(ctx).EmitKV(
|
||||
types.EventTypeTransfer,
|
||||
event.NewAttribute(types.AttributeKeyRecipient, toAddrString),
|
||||
event.NewAttribute(types.AttributeKeySender, fromAddrString),
|
||||
event.NewAttribute(sdk.AttributeKeyAmount, amt.String()),
|
||||
)
|
||||
}
|
||||
|
||||
// GetSupply retrieves the Supply from store
|
||||
func (k Keeper) GetSupply(ctx context.Context, denom string) sdk.Coin {
|
||||
amt, err := k.supply.Get(ctx, denom)
|
||||
if err != nil {
|
||||
return sdk.NewCoin(denom, math.ZeroInt())
|
||||
}
|
||||
return sdk.NewCoin(denom, amt)
|
||||
}
|
||||
|
||||
// GetBalance returns the balance of a specific denomination for a given account
|
||||
// by address.
|
||||
func (k Keeper) GetBalance(ctx context.Context, addr []byte, denom string) sdk.Coin {
|
||||
amt, err := k.balances.Get(ctx, collections.Join(addr, denom))
|
||||
if err != nil {
|
||||
return sdk.NewCoin(denom, math.ZeroInt())
|
||||
}
|
||||
return sdk.NewCoin(denom, amt)
|
||||
}
|
||||
|
||||
// subUnlockedCoins removes the unlocked amt coins of the given account.
|
||||
// An error is returned if the resulting balance is negative.
|
||||
//
|
||||
// CONTRACT: The provided amount (amt) must be valid, non-negative coins.
|
||||
//
|
||||
// A coin_spent event is emitted after the operation.
|
||||
func (k Keeper) subUnlockedCoins(ctx context.Context, addr []byte, amt sdk.Coins) error {
|
||||
for _, coin := range amt {
|
||||
balance := k.GetBalance(ctx, addr, coin.Denom)
|
||||
spendable := sdk.Coins{balance}
|
||||
|
||||
_, hasNeg := spendable.SafeSub(coin)
|
||||
if hasNeg {
|
||||
if len(spendable) == 0 {
|
||||
spendable = sdk.Coins{sdk.Coin{Denom: coin.Denom, Amount: math.ZeroInt()}}
|
||||
}
|
||||
return errorsmod.Wrapf(
|
||||
sdkerrors.ErrInsufficientFunds,
|
||||
"spendable balance %s is smaller than %s",
|
||||
spendable, coin,
|
||||
)
|
||||
}
|
||||
|
||||
newBalance := balance.Sub(coin)
|
||||
|
||||
if err := k.setBalance(ctx, addr, newBalance); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
addrStr, err := k.addressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return k.EventService.EventManager(ctx).EmitKV(
|
||||
types.EventTypeCoinSpent,
|
||||
event.NewAttribute(types.AttributeKeySpender, addrStr),
|
||||
event.NewAttribute(sdk.AttributeKeyAmount, amt.String()),
|
||||
)
|
||||
}
|
||||
|
||||
// addCoins increases the balance of the given address by the specified amount.
|
||||
//
|
||||
// CONTRACT: The provided amount (amt) must be valid, non-negative coins.
|
||||
//
|
||||
// It emits a coin_received event after the operation.
|
||||
func (k Keeper) addCoins(ctx context.Context, addr []byte, amt sdk.Coins) error {
|
||||
for _, coin := range amt {
|
||||
balance := k.GetBalance(ctx, addr, coin.Denom)
|
||||
newBalance := balance.Add(coin)
|
||||
|
||||
err := k.setBalance(ctx, addr, newBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
addrStr, err := k.addressCodec.BytesToString(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return k.EventService.EventManager(ctx).EmitKV(
|
||||
types.EventTypeCoinReceived,
|
||||
event.NewAttribute(types.AttributeKeyReceiver, addrStr),
|
||||
event.NewAttribute(sdk.AttributeKeyAmount, amt.String()),
|
||||
)
|
||||
}
|
||||
|
||||
// setSupply sets the supply for the given coin
|
||||
func (k Keeper) setSupply(ctx context.Context, coin sdk.Coin) {
|
||||
// Bank invariants and IBC requires to remove zero coins.
|
||||
if coin.IsZero() {
|
||||
_ = k.supply.Remove(ctx, coin.Denom)
|
||||
} else {
|
||||
_ = k.supply.Set(ctx, coin.Denom, coin.Amount)
|
||||
}
|
||||
}
|
||||
|
||||
// setBalance sets the coin balance for an account by address.
|
||||
func (k Keeper) setBalance(ctx context.Context, addr []byte, balance sdk.Coin) error {
|
||||
if !balance.IsValid() {
|
||||
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, balance.String())
|
||||
}
|
||||
|
||||
// x/bank invariants prohibit persistence of zero balances
|
||||
if balance.IsZero() {
|
||||
err := k.balances.Remove(ctx, collections.Join(addr, balance.Denom))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return k.balances.Set(ctx, collections.Join(addr, balance.Denom), balance.Amount)
|
||||
}
|
||||
|
||||
func newBalancesIndexes(sb *collections.SchemaBuilder) BalancesIndexes {
|
||||
return BalancesIndexes{
|
||||
Denom: indexes.NewReversePair[math.Int](
|
||||
sb, types.DenomAddressPrefix, "address_by_denom_index",
|
||||
collections.PairKeyCodec(collections.BytesKey, collections.StringKey),
|
||||
indexes.WithReversePairUncheckedValue(), // denom to address indexes were stored as Key: Join(denom, address) Value: []byte{0}, this will migrate the value to []byte{} in a lazy way.
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type BalancesIndexes struct {
|
||||
Denom *indexes.ReversePair[[]byte, string, math.Int]
|
||||
}
|
||||
|
||||
186
x/bank/v2/keeper/keeper_test.go
Normal file
186
x/bank/v2/keeper/keeper_test.go
Normal file
@ -0,0 +1,186 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/header"
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/bank/v2/keeper"
|
||||
banktestutil "cosmossdk.io/x/bank/v2/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/v2/types"
|
||||
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
const (
|
||||
fooDenom = "foo"
|
||||
barDenom = "bar"
|
||||
)
|
||||
|
||||
var (
|
||||
burnerAcc = authtypes.NewEmptyModuleAccount(authtypes.Burner, authtypes.Burner, authtypes.Staking)
|
||||
mintAcc = authtypes.NewEmptyModuleAccount(banktypes.MintModuleName, authtypes.Minter)
|
||||
|
||||
accAddrs = []sdk.AccAddress{
|
||||
sdk.AccAddress([]byte("addr1_______________")),
|
||||
sdk.AccAddress([]byte("addr2_______________")),
|
||||
sdk.AccAddress([]byte("addr3_______________")),
|
||||
sdk.AccAddress([]byte("addr4_______________")),
|
||||
sdk.AccAddress([]byte("addr5_______________")),
|
||||
}
|
||||
)
|
||||
|
||||
func newFooCoin(amt int64) sdk.Coin {
|
||||
return sdk.NewInt64Coin(fooDenom, amt)
|
||||
}
|
||||
|
||||
func newBarCoin(amt int64) sdk.Coin {
|
||||
return sdk.NewInt64Coin(barDenom, amt)
|
||||
}
|
||||
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx context.Context
|
||||
bankKeeper keeper.Keeper
|
||||
addressCodec address.Codec
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(KeeperTestSuite))
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
key := storetypes.NewKVStoreKey(banktypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test"))
|
||||
ctx := testCtx.Ctx.WithHeaderInfo(header.Info{Time: time.Now()})
|
||||
encCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{})
|
||||
|
||||
env := runtime.NewEnvironment(runtime.NewKVStoreService(key), coretesting.NewNopLogger())
|
||||
|
||||
ac := codectestutil.CodecOptions{}.GetAddressCodec()
|
||||
authority := authtypes.NewModuleAddress("gov")
|
||||
|
||||
suite.ctx = ctx
|
||||
suite.bankKeeper = *keeper.NewKeeper(
|
||||
authority,
|
||||
ac,
|
||||
env,
|
||||
encCfg.Codec,
|
||||
)
|
||||
suite.addressCodec = ac
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSendCoins_Acount_To_Account() {
|
||||
ctx := suite.ctx
|
||||
require := suite.Require()
|
||||
balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
|
||||
sendAmt := sdk.NewCoins(newFooCoin(10), newBarCoin(10))
|
||||
|
||||
// Try send with empty balances
|
||||
err := suite.bankKeeper.SendCoins(ctx, accAddrs[0], accAddrs[1], sendAmt)
|
||||
require.Error(err)
|
||||
|
||||
// Set balances for acc0 and then try send to acc1
|
||||
require.NoError(banktestutil.FundAccount(ctx, suite.bankKeeper, accAddrs[0], balances))
|
||||
require.NoError(suite.bankKeeper.SendCoins(ctx, accAddrs[0], accAddrs[1], sendAmt))
|
||||
|
||||
// Check balances
|
||||
acc0FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], fooDenom)
|
||||
require.Equal(acc0FooBalance.Amount, math.NewInt(90))
|
||||
acc0BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], barDenom)
|
||||
require.Equal(acc0BarBalance.Amount, math.NewInt(40))
|
||||
acc1FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[1], fooDenom)
|
||||
require.Equal(acc1FooBalance.Amount, math.NewInt(10))
|
||||
acc1BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[1], barDenom)
|
||||
require.Equal(acc1BarBalance.Amount, math.NewInt(10))
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSendCoins_Acount_To_Module() {
|
||||
ctx := suite.ctx
|
||||
require := suite.Require()
|
||||
balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
|
||||
sendAmt := sdk.NewCoins(newFooCoin(10), newBarCoin(10))
|
||||
|
||||
// Try send with empty balances
|
||||
err := suite.bankKeeper.SendCoins(ctx, accAddrs[0], burnerAcc.GetAddress(), sendAmt)
|
||||
require.Error(err)
|
||||
|
||||
// Set balances for acc0 and then try send to acc1
|
||||
require.NoError(banktestutil.FundAccount(ctx, suite.bankKeeper, accAddrs[0], balances))
|
||||
require.NoError(suite.bankKeeper.SendCoins(ctx, accAddrs[0], burnerAcc.GetAddress(), sendAmt))
|
||||
|
||||
// Check balances
|
||||
acc0FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], fooDenom)
|
||||
require.Equal(acc0FooBalance.Amount, math.NewInt(90))
|
||||
acc0BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[0], barDenom)
|
||||
require.Equal(acc0BarBalance.Amount, math.NewInt(40))
|
||||
burnerFooBalance := suite.bankKeeper.GetBalance(ctx, burnerAcc.GetAddress(), fooDenom)
|
||||
require.Equal(burnerFooBalance.Amount, math.NewInt(10))
|
||||
burnerBarBalance := suite.bankKeeper.GetBalance(ctx, burnerAcc.GetAddress(), barDenom)
|
||||
require.Equal(burnerBarBalance.Amount, math.NewInt(10))
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSendCoins_Module_To_Account() {
|
||||
ctx := suite.ctx
|
||||
require := suite.Require()
|
||||
balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
|
||||
|
||||
require.NoError(suite.bankKeeper.MintCoins(ctx, mintAcc.GetAddress(), balances))
|
||||
|
||||
// Try send from burner module
|
||||
err := suite.bankKeeper.SendCoins(ctx, burnerAcc.GetAddress(), accAddrs[4], balances)
|
||||
require.Error(err)
|
||||
|
||||
// Send from mint module
|
||||
err = suite.bankKeeper.SendCoins(ctx, mintAcc.GetAddress(), accAddrs[4], balances)
|
||||
require.NoError(err)
|
||||
|
||||
// Check balances
|
||||
acc4FooBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[4], fooDenom)
|
||||
require.Equal(acc4FooBalance.Amount, math.NewInt(100))
|
||||
acc4BarBalance := suite.bankKeeper.GetBalance(ctx, accAddrs[4], barDenom)
|
||||
require.Equal(acc4BarBalance.Amount, math.NewInt(50))
|
||||
mintFooBalance := suite.bankKeeper.GetBalance(ctx, mintAcc.GetAddress(), fooDenom)
|
||||
require.Equal(mintFooBalance.Amount, math.NewInt(0))
|
||||
mintBarBalance := suite.bankKeeper.GetBalance(ctx, mintAcc.GetAddress(), barDenom)
|
||||
require.Equal(mintBarBalance.Amount, math.NewInt(0))
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestSendCoins_Module_To_Module() {
|
||||
ctx := suite.ctx
|
||||
require := suite.Require()
|
||||
balances := sdk.NewCoins(newFooCoin(100), newBarCoin(50))
|
||||
|
||||
require.NoError(suite.bankKeeper.MintCoins(ctx, mintAcc.GetAddress(), balances))
|
||||
|
||||
// Try send from burner module
|
||||
err := suite.bankKeeper.SendCoins(ctx, burnerAcc.GetAddress(), mintAcc.GetAddress(), sdk.NewCoins(newFooCoin(100), newBarCoin(50)))
|
||||
require.Error(err)
|
||||
|
||||
// Send from mint module to burn module
|
||||
err = suite.bankKeeper.SendCoins(ctx, mintAcc.GetAddress(), burnerAcc.GetAddress(), sdk.NewCoins(newFooCoin(100), newBarCoin(50)))
|
||||
require.NoError(err)
|
||||
|
||||
// Check balances
|
||||
burnerFooBalance := suite.bankKeeper.GetBalance(ctx, burnerAcc.GetAddress(), fooDenom)
|
||||
require.Equal(burnerFooBalance.Amount, math.NewInt(100))
|
||||
burnerBarBalance := suite.bankKeeper.GetBalance(ctx, burnerAcc.GetAddress(), barDenom)
|
||||
require.Equal(burnerBarBalance.Amount, math.NewInt(50))
|
||||
mintFooBalance := suite.bankKeeper.GetBalance(ctx, mintAcc.GetAddress(), fooDenom)
|
||||
require.Equal(mintFooBalance.Amount, math.NewInt(0))
|
||||
mintBarBalance := suite.bankKeeper.GetBalance(ctx, mintAcc.GetAddress(), barDenom)
|
||||
require.Equal(mintBarBalance.Amount, math.NewInt(0))
|
||||
}
|
||||
218
x/bank/v2/testutil/expected_keepers_mocks.go
Normal file
218
x/bank/v2/testutil/expected_keepers_mocks.go
Normal file
@ -0,0 +1,218 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: x/bank/types/expected_keepers.go
|
||||
|
||||
// Package testutil is a generated GoMock package.
|
||||
package testutil
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
address "cosmossdk.io/core/address"
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
type MockAccountKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper.
|
||||
type MockAccountKeeperMockRecorder struct {
|
||||
mock *MockAccountKeeper
|
||||
}
|
||||
|
||||
// NewMockAccountKeeper creates a new mock instance.
|
||||
func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper {
|
||||
mock := &MockAccountKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AddressCodec mocks base method.
|
||||
func (m *MockAccountKeeper) AddressCodec() address.Codec {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddressCodec")
|
||||
ret0, _ := ret[0].(address.Codec)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AddressCodec indicates an expected call of AddressCodec.
|
||||
func (mr *MockAccountKeeperMockRecorder) AddressCodec() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressCodec", reflect.TypeOf((*MockAccountKeeper)(nil).AddressCodec))
|
||||
}
|
||||
|
||||
// GetAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddress) types.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAccount", ctx, addr)
|
||||
ret0, _ := ret[0].(types.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetAccount indicates an expected call of GetAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr)
|
||||
}
|
||||
|
||||
// GetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAccount(ctx context.Context, moduleName string) types.ModuleAccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAccount", ctx, moduleName)
|
||||
ret0, _ := ret[0].(types.ModuleAccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAccount indicates an expected call of GetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAccount(ctx, moduleName interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccount), ctx, moduleName)
|
||||
}
|
||||
|
||||
// GetModuleAccountAndPermissions mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAccountAndPermissions(ctx context.Context, moduleName string) (types.ModuleAccountI, []string) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAccountAndPermissions", ctx, moduleName)
|
||||
ret0, _ := ret[0].(types.ModuleAccountI)
|
||||
ret1, _ := ret[1].([]string)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetModuleAccountAndPermissions indicates an expected call of GetModuleAccountAndPermissions.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAccountAndPermissions(ctx, moduleName interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAccountAndPermissions", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAccountAndPermissions), ctx, moduleName)
|
||||
}
|
||||
|
||||
// GetModuleAddress mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAddress(moduleName string) types.AccAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddress", moduleName)
|
||||
ret0, _ := ret[0].(types.AccAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModuleAddress indicates an expected call of GetModuleAddress.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddress(moduleName interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddress", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddress), moduleName)
|
||||
}
|
||||
|
||||
// GetModuleAddressAndPermissions mocks base method.
|
||||
func (m *MockAccountKeeper) GetModuleAddressAndPermissions(moduleName string) (types.AccAddress, []string) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModuleAddressAndPermissions", moduleName)
|
||||
ret0, _ := ret[0].(types.AccAddress)
|
||||
ret1, _ := ret[1].([]string)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetModuleAddressAndPermissions indicates an expected call of GetModuleAddressAndPermissions.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModuleAddressAndPermissions(moduleName interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModuleAddressAndPermissions", reflect.TypeOf((*MockAccountKeeper)(nil).GetModuleAddressAndPermissions), moduleName)
|
||||
}
|
||||
|
||||
// GetModulePermissions mocks base method.
|
||||
func (m *MockAccountKeeper) GetModulePermissions() map[string]types0.PermissionsForAddress {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetModulePermissions")
|
||||
ret0, _ := ret[0].(map[string]types0.PermissionsForAddress)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetModulePermissions indicates an expected call of GetModulePermissions.
|
||||
func (mr *MockAccountKeeperMockRecorder) GetModulePermissions() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetModulePermissions", reflect.TypeOf((*MockAccountKeeper)(nil).GetModulePermissions))
|
||||
}
|
||||
|
||||
// HasAccount mocks base method.
|
||||
func (m *MockAccountKeeper) HasAccount(ctx context.Context, addr types.AccAddress) bool {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasAccount", ctx, addr)
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// HasAccount indicates an expected call of HasAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) HasAccount(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasAccount", reflect.TypeOf((*MockAccountKeeper)(nil).HasAccount), ctx, addr)
|
||||
}
|
||||
|
||||
// NewAccount mocks base method.
|
||||
func (m *MockAccountKeeper) NewAccount(arg0 context.Context, arg1 types.AccountI) types.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NewAccount", arg0, arg1)
|
||||
ret0, _ := ret[0].(types.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// NewAccount indicates an expected call of NewAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) NewAccount(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccount", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccount), arg0, arg1)
|
||||
}
|
||||
|
||||
// NewAccountWithAddress mocks base method.
|
||||
func (m *MockAccountKeeper) NewAccountWithAddress(ctx context.Context, addr types.AccAddress) types.AccountI {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "NewAccountWithAddress", ctx, addr)
|
||||
ret0, _ := ret[0].(types.AccountI)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// NewAccountWithAddress indicates an expected call of NewAccountWithAddress.
|
||||
func (mr *MockAccountKeeperMockRecorder) NewAccountWithAddress(ctx, addr interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccountWithAddress", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccountWithAddress), ctx, addr)
|
||||
}
|
||||
|
||||
// SetAccount mocks base method.
|
||||
func (m *MockAccountKeeper) SetAccount(ctx context.Context, acc types.AccountI) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetAccount", ctx, acc)
|
||||
}
|
||||
|
||||
// SetAccount indicates an expected call of SetAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) SetAccount(ctx, acc interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetAccount), ctx, acc)
|
||||
}
|
||||
|
||||
// SetModuleAccount mocks base method.
|
||||
func (m *MockAccountKeeper) SetModuleAccount(ctx context.Context, macc types.ModuleAccountI) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetModuleAccount", ctx, macc)
|
||||
}
|
||||
|
||||
// SetModuleAccount indicates an expected call of SetModuleAccount.
|
||||
func (mr *MockAccountKeeperMockRecorder) SetModuleAccount(ctx, macc interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetModuleAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetModuleAccount), ctx, macc)
|
||||
}
|
||||
|
||||
// ValidatePermissions mocks base method.
|
||||
func (m *MockAccountKeeper) ValidatePermissions(macc types.ModuleAccountI) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatePermissions", macc)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ValidatePermissions indicates an expected call of ValidatePermissions.
|
||||
func (mr *MockAccountKeeperMockRecorder) ValidatePermissions(macc interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatePermissions", reflect.TypeOf((*MockAccountKeeper)(nil).ValidatePermissions), macc)
|
||||
}
|
||||
16
x/bank/v2/testutil/helpers.go
Normal file
16
x/bank/v2/testutil/helpers.go
Normal file
@ -0,0 +1,16 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
bankkeeper "cosmossdk.io/x/bank/v2/keeper"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// FundAccount is a utility function that funds an account by minting and
|
||||
// sending the coins to the address. This should be used for testing purposes
|
||||
// only!
|
||||
func FundAccount(ctx context.Context, bankKeeper bankkeeper.Keeper, addr []byte, amounts sdk.Coins) error {
|
||||
return bankKeeper.MintCoins(ctx, addr, amounts)
|
||||
}
|
||||
24
x/bank/v2/types/events.go
Normal file
24
x/bank/v2/types/events.go
Normal file
@ -0,0 +1,24 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// bank module event types
|
||||
const (
|
||||
EventTypeTransfer = "transfer"
|
||||
|
||||
AttributeKeyRecipient = "recipient"
|
||||
AttributeKeySender = sdk.AttributeKeySender
|
||||
|
||||
// supply and balance tracking events name and attributes
|
||||
EventTypeCoinSpent = "coin_spent"
|
||||
EventTypeCoinReceived = "coin_received"
|
||||
EventTypeCoinMint = "coinbase" // NOTE(fdymylja): using mint clashes with mint module event
|
||||
EventTypeCoinBurn = "burn"
|
||||
|
||||
AttributeKeySpender = "spender"
|
||||
AttributeKeyReceiver = "receiver"
|
||||
AttributeKeyMinter = "minter"
|
||||
AttributeKeyBurner = "burner"
|
||||
)
|
||||
1
x/bank/v2/types/expected_keepers.go
Normal file
1
x/bank/v2/types/expected_keepers.go
Normal file
@ -0,0 +1 @@
|
||||
package types
|
||||
@ -1,14 +1,34 @@
|
||||
package types
|
||||
|
||||
import "cosmossdk.io/collections"
|
||||
import (
|
||||
"cosmossdk.io/collections"
|
||||
)
|
||||
|
||||
const (
|
||||
// ModuleName is the name of the module
|
||||
ModuleName = "bankv2"
|
||||
|
||||
// StoreKey defines the primary module store key
|
||||
StoreKey = ModuleName
|
||||
|
||||
// GovModuleName duplicates the gov module's name to avoid a dependency with x/gov.
|
||||
GovModuleName = "gov"
|
||||
|
||||
// MintModuleName duplicates the mint module's name to avoid a cyclic dependency with x/mint.
|
||||
// It should be synced with the mint module's name if it is ever changed.
|
||||
// See: https://github.com/cosmos/cosmos-sdk/blob/0e34478eb7420b69869ed50f129fc274a97a9b06/x/mint/types/keys.go#L13
|
||||
MintModuleName = "mint"
|
||||
)
|
||||
|
||||
// ParamsKey is the prefix for x/bank/v2 parameters
|
||||
var ParamsKey = collections.NewPrefix(2)
|
||||
var (
|
||||
// ParamsKey is the prefix for x/bank/v2 parameters
|
||||
ParamsKey = collections.NewPrefix(2)
|
||||
|
||||
// BalancesPrefix is the prefix for the account balances store. We use a byte
|
||||
// (instead of `[]byte("balances")` to save some disk space).
|
||||
BalancesPrefix = collections.NewPrefix(3)
|
||||
|
||||
DenomAddressPrefix = collections.NewPrefix(4)
|
||||
|
||||
SupplyKey = collections.NewPrefix(5)
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user