feat(x/precisebank): Implement GetBalance (#1916)

Implement GetBalance for extended balances which passes through to `x/bank` for non-extended denoms. This diverges from `x/evmutil` behavior which will panic on non-"akava" calls.

Add bank / account keeper mocks for testing, with mockery config for [mockery package setup](https://vektra.github.io/mockery/latest/migrating_to_packages/)
This commit is contained in:
drklee3 2024-05-21 14:11:13 -07:00 committed by GitHub
parent dbc3ad7fd2
commit 4cf41d18c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1103 additions and 48 deletions

16
.mockery.yaml Normal file
View File

@ -0,0 +1,16 @@
# Generate EXPECT() methods, type-safe methods to generate call expectations
with-expecter: true
# Generate mocks in adjacent mocks directory to the interfaces
dir: "{{.InterfaceDir}}/mocks"
mockname: "Mock{{.InterfaceName}}"
outpkg: "mocks"
filename: "Mock{{.InterfaceName}}.go"
packages:
github.com/kava-labs/kava/x/precisebank/types:
# package-specific config
config:
interfaces:
AccountKeeper:
BankKeeper:

View File

@ -554,6 +554,8 @@ func NewApp(
app.precisebankKeeper = precisebankkeeper.NewKeeper( app.precisebankKeeper = precisebankkeeper.NewKeeper(
app.appCodec, app.appCodec,
keys[precisebanktypes.StoreKey], keys[precisebanktypes.StoreKey],
app.bankKeeper,
app.accountKeeper,
) )
evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper)

View File

@ -11,7 +11,7 @@ import (
) )
func TestSetGetFractionalBalance(t *testing.T) { func TestSetGetFractionalBalance(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
addr := sdk.AccAddress([]byte("test-address")) addr := sdk.AccAddress([]byte("test-address"))
@ -97,7 +97,7 @@ func TestSetGetFractionalBalance(t *testing.T) {
} }
func TestSetFractionalBalance_InvalidAddr(t *testing.T) { func TestSetFractionalBalance_InvalidAddr(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
require.PanicsWithError( require.PanicsWithError(
@ -111,7 +111,7 @@ func TestSetFractionalBalance_InvalidAddr(t *testing.T) {
} }
func TestSetFractionalBalance_ZeroDeletes(t *testing.T) { func TestSetFractionalBalance_ZeroDeletes(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
addr := sdk.AccAddress([]byte("test-address")) addr := sdk.AccAddress([]byte("test-address"))
@ -140,7 +140,7 @@ func TestSetFractionalBalance_ZeroDeletes(t *testing.T) {
} }
func TestIterateFractionalBalances(t *testing.T) { func TestIterateFractionalBalances(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
addrs := []sdk.AccAddress{} addrs := []sdk.AccAddress{}
@ -168,7 +168,7 @@ func TestIterateFractionalBalances(t *testing.T) {
} }
func TestGetAggregateSumFractionalBalances(t *testing.T) { func TestGetAggregateSumFractionalBalances(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
// Set balances from 1 to 10 // Set balances from 1 to 10

View File

@ -17,6 +17,7 @@ func RegisterInvariants(
ir.RegisterRoute(types.ModuleName, "balance-remainder-total", BalancedFractionalTotalInvariant(k)) ir.RegisterRoute(types.ModuleName, "balance-remainder-total", BalancedFractionalTotalInvariant(k))
ir.RegisterRoute(types.ModuleName, "valid-fractional-balances", ValidFractionalAmountsInvariant(k)) ir.RegisterRoute(types.ModuleName, "valid-fractional-balances", ValidFractionalAmountsInvariant(k))
ir.RegisterRoute(types.ModuleName, "valid-remainder-amount", ValidRemainderAmountInvariant(k)) ir.RegisterRoute(types.ModuleName, "valid-remainder-amount", ValidRemainderAmountInvariant(k))
ir.RegisterRoute(types.ModuleName, "fractional-denom-not-in-bank", FractionalDenomNotInBankInvariant(k))
} }
// AllInvariants runs all invariants of the X/precisebank module. // AllInvariants runs all invariants of the X/precisebank module.
@ -37,6 +38,11 @@ func AllInvariants(k Keeper) sdk.Invariant {
return res, stop return res, stop
} }
res, stop = FractionalDenomNotInBankInvariant(k)(ctx)
if stop {
return res, stop
}
return "", false return "", false
} }
} }
@ -121,3 +127,32 @@ func BalancedFractionalTotalInvariant(k Keeper) sdk.Invariant {
), broken ), broken
} }
} }
// FractionalDenomNotInBankInvariant checks that the bank does not hold any
// fractional denoms. These assets, e.g. akava, should only exist in the
// x/precisebank module as this is a decimal extension of ukava that shares
// the same total supply and is effectively the same asset. ukava held by this
// module in x/bank backs all fractional balances in x/precisebank. If akava
// somehow ends up in x/bank, then it would both break all expectations of this
// module as well as be double-counted in the total supply.
func FractionalDenomNotInBankInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
extBankSupply := k.bk.GetSupply(ctx, types.ExtendedCoinDenom)
broken := !extBankSupply.IsZero()
msg := ""
if broken {
msg = fmt.Sprintf(
"x/bank should not hold any %v but has supply of %v",
types.ExtendedCoinDenom,
extBankSupply,
)
}
return sdk.FormatInvariant(
types.ModuleName, "fractional-denom-not-in-bank",
msg,
), broken
}
}

View File

@ -10,28 +10,26 @@ import (
"github.com/kava-labs/kava/x/precisebank/keeper" "github.com/kava-labs/kava/x/precisebank/keeper"
"github.com/kava-labs/kava/x/precisebank/types" "github.com/kava-labs/kava/x/precisebank/types"
"github.com/kava-labs/kava/x/precisebank/types/mocks"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestBalancedFractionalTotalInvariant(t *testing.T) { func TestBalancedFractionalTotalInvariant(t *testing.T) {
var ctx sdk.Context
var k keeper.Keeper
tests := []struct { tests := []struct {
name string name string
setupFn func() setupFn func(ctx sdk.Context, k keeper.Keeper)
wantBroken bool wantBroken bool
wantMsg string wantMsg string
}{ }{
{ {
"valid - empty state", "valid - empty state",
func() {}, func(_ sdk.Context, _ keeper.Keeper) {},
false, false,
"", "",
}, },
{ {
"valid - balances, 0 remainder", "valid - balances, 0 remainder",
func() { func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2))
}, },
@ -40,7 +38,7 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
}, },
{ {
"valid - balances, non-zero remainder", "valid - balances, non-zero remainder",
func() { func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1))
@ -51,7 +49,7 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
}, },
{ {
"invalid - balances, 0 remainder", "invalid - balances, 0 remainder",
func() { func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(1))
}, },
@ -60,7 +58,7 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
}, },
{ {
"invalid - invalid balances, non-zero (insufficient) remainder", "invalid - invalid balances, non-zero (insufficient) remainder",
func() { func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2))
k.SetRemainderAmount(ctx, sdkmath.OneInt()) k.SetRemainderAmount(ctx, sdkmath.OneInt())
@ -70,7 +68,7 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
}, },
{ {
"invalid - invalid balances, non-zero (excess) remainder", "invalid - invalid balances, non-zero (excess) remainder",
func() { func(ctx sdk.Context, k keeper.Keeper) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2).SubRaw(2))
k.SetRemainderAmount(ctx, sdkmath.NewInt(5)) k.SetRemainderAmount(ctx, sdkmath.NewInt(5))
@ -83,13 +81,12 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Reset each time // Reset each time
tk := NewTestKeeper() td := NewMockedTestData(t)
ctx, k = tk.ctx, tk.keeper
tt.setupFn() tt.setupFn(td.ctx, td.keeper)
invariantFn := keeper.BalancedFractionalTotalInvariant(k) invariantFn := keeper.BalancedFractionalTotalInvariant(td.keeper)
msg, broken := invariantFn(ctx) msg, broken := invariantFn(td.ctx)
if tt.wantBroken { if tt.wantBroken {
require.True(t, broken, "invariant should be broken but is not") require.True(t, broken, "invariant should be broken but is not")
@ -102,25 +99,21 @@ func TestBalancedFractionalTotalInvariant(t *testing.T) {
} }
func TestValidFractionalAmountsInvariant(t *testing.T) { func TestValidFractionalAmountsInvariant(t *testing.T) {
var ctx sdk.Context
var k keeper.Keeper
var storeKey storetypes.StoreKey
tests := []struct { tests := []struct {
name string name string
setupFn func() setupFn func(ctx sdk.Context, k keeper.Keeper, storeKey storetypes.StoreKey)
wantBroken bool wantBroken bool
wantMsg string wantMsg string
}{ }{
{ {
"valid - empty state", "valid - empty state",
func() {}, func(_ sdk.Context, _ keeper.Keeper, _ storetypes.StoreKey) {},
false, false,
"", "",
}, },
{ {
"valid - valid balances", "valid - valid balances",
func() { func(ctx sdk.Context, k keeper.Keeper, _ storetypes.StoreKey) {
k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{1}, types.ConversionFactor().QuoRaw(2))
k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2)) k.SetFractionalBalance(ctx, sdk.AccAddress{2}, types.ConversionFactor().QuoRaw(2))
}, },
@ -129,7 +122,7 @@ func TestValidFractionalAmountsInvariant(t *testing.T) {
}, },
{ {
"invalid - exceeds max balance", "invalid - exceeds max balance",
func() { func(ctx sdk.Context, _ keeper.Keeper, storeKey storetypes.StoreKey) {
// Requires manual store manipulation so it is unlikely to have // Requires manual store manipulation so it is unlikely to have
// invalid state in practice. SetFractionalBalance will validate // invalid state in practice. SetFractionalBalance will validate
// before setting. // before setting.
@ -151,13 +144,65 @@ func TestValidFractionalAmountsInvariant(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Reset each time // Reset each time
tk := NewTestKeeper() td := NewMockedTestData(t)
ctx, k, storeKey = tk.ctx, tk.keeper, tk.storeKey
tt.setupFn() tt.setupFn(td.ctx, td.keeper, td.storeKey)
invariantFn := keeper.ValidFractionalAmountsInvariant(k) invariantFn := keeper.ValidFractionalAmountsInvariant(td.keeper)
msg, broken := invariantFn(ctx) msg, broken := invariantFn(td.ctx)
if tt.wantBroken {
require.True(t, broken, "invariant should be broken but is not")
require.Equal(t, tt.wantMsg, msg)
} else {
require.False(t, broken, "invariant should not be broken but is")
}
})
}
}
func TestFractionalDenomNotInBankInvariant(t *testing.T) {
tests := []struct {
name string
setupFn func(ctx sdk.Context, bk *mocks.MockBankKeeper)
wantBroken bool
wantMsg string
}{
{
"valid - integer denom (ukava) supply",
func(ctx sdk.Context, bk *mocks.MockBankKeeper) {
// No fractional balance in x/bank
// This also enforces there is no GetSupply() call for IntegerCoinDenom / ukava
bk.EXPECT().
GetSupply(ctx, types.ExtendedCoinDenom).
Return(sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt())).
Once()
},
false,
"",
},
{
"invalid - x/bank contains fractional denom (akava)",
func(ctx sdk.Context, bk *mocks.MockBankKeeper) {
bk.EXPECT().
GetSupply(ctx, types.ExtendedCoinDenom).
Return(sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000))).
Once()
},
true,
"precisebank: fractional-denom-not-in-bank invariant\nx/bank should not hold any akava but has supply of 1000akava\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Reset each time
td := NewMockedTestData(t)
tt.setupFn(td.ctx, td.bk)
invariantFn := keeper.FractionalDenomNotInBankInvariant(td.keeper)
msg, broken := invariantFn(td.ctx)
if tt.wantBroken { if tt.wantBroken {
require.True(t, broken, "invariant should be broken but is not") require.True(t, broken, "invariant should be broken but is not")

View File

@ -3,21 +3,43 @@ package keeper
import ( import (
"github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types" storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/kava-labs/kava/x/precisebank/types"
) )
// TODO: Enforce that Keeper implements the expected keeper interfaces // Enforce that Keeper implements the expected keeper interfaces
// var _ types.BankKeeper = Keeper{} var _ evmtypes.BankKeeper = Keeper{}
// Keeper defines the precisebank module's keeper // Keeper defines the precisebank module's keeper
type Keeper struct { type Keeper struct {
cdc codec.BinaryCodec cdc codec.BinaryCodec
storeKey storetypes.StoreKey storeKey storetypes.StoreKey
bk types.BankKeeper
ak types.AccountKeeper
} }
// NewKeeper creates a new keeper // NewKeeper creates a new keeper
func NewKeeper(cdc codec.BinaryCodec, storeKey storetypes.StoreKey) Keeper { func NewKeeper(
cdc codec.BinaryCodec,
storeKey storetypes.StoreKey,
bk types.BankKeeper,
ak types.AccountKeeper,
) Keeper {
return Keeper{ return Keeper{
cdc: cdc, cdc: cdc,
storeKey: storeKey, storeKey: storeKey,
bk: bk,
ak: ak,
} }
} }
func (k Keeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error {
panic("unimplemented")
}
func (k Keeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error {
panic("unimplemented")
}

View File

@ -1,6 +1,8 @@
package keeper_test package keeper_test
import ( import (
"testing"
storetypes "github.com/cosmos/cosmos-sdk/store/types" storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
@ -8,29 +10,39 @@ import (
"github.com/kava-labs/kava/app" "github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/x/precisebank/keeper" "github.com/kava-labs/kava/x/precisebank/keeper"
"github.com/kava-labs/kava/x/precisebank/types" "github.com/kava-labs/kava/x/precisebank/types"
"github.com/kava-labs/kava/x/precisebank/types/mocks"
) )
// testKeeper defines necessary fields for testing keeper store methods that // testData defines necessary fields for testing keeper store methods and mocks
// don't require a full app setup. // for unit tests without full app setup.
type testKeeper struct { type testData struct {
ctx sdk.Context ctx sdk.Context
keeper keeper.Keeper keeper keeper.Keeper
storeKey *storetypes.KVStoreKey storeKey *storetypes.KVStoreKey
bk *mocks.MockBankKeeper
ak *mocks.MockAccountKeeper
} }
func NewTestKeeper() testKeeper { // NewMockedTestData creates a new testData instance with mocked bank and
// account keepers.
func NewMockedTestData(t *testing.T) testData {
storeKey := sdk.NewKVStoreKey(types.ModuleName) storeKey := sdk.NewKVStoreKey(types.ModuleName)
// Not required by module, but needs to be non-nil for context // Not required by module, but needs to be non-nil for context
tKey := sdk.NewTransientStoreKey("transient_test") tKey := sdk.NewTransientStoreKey("transient_test")
ctx := testutil.DefaultContext(storeKey, tKey) ctx := testutil.DefaultContext(storeKey, tKey)
bk := mocks.NewMockBankKeeper(t)
ak := mocks.NewMockAccountKeeper(t)
tApp := app.NewTestApp() tApp := app.NewTestApp()
cdc := tApp.AppCodec() cdc := tApp.AppCodec()
k := keeper.NewKeeper(cdc, storeKey) k := keeper.NewKeeper(cdc, storeKey, bk, ak)
return testKeeper{ return testData{
ctx: ctx, ctx: ctx,
keeper: k, keeper: k,
storeKey: storeKey, storeKey: storeKey,
bk: bk,
ak: ak,
} }
} }

View File

@ -9,7 +9,7 @@ import (
) )
func TestGetSetRemainderAmount(t *testing.T) { func TestGetSetRemainderAmount(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey
// Set amount // Set amount
@ -31,7 +31,7 @@ func TestGetSetRemainderAmount(t *testing.T) {
} }
func TestInvalidRemainderAmount(t *testing.T) { func TestInvalidRemainderAmount(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k := tk.ctx, tk.keeper ctx, k := tk.ctx, tk.keeper
// Set negative amount // Set negative amount
@ -46,7 +46,7 @@ func TestInvalidRemainderAmount(t *testing.T) {
} }
func TestDeleteRemainderAmount(t *testing.T) { func TestDeleteRemainderAmount(t *testing.T) {
tk := NewTestKeeper() tk := NewMockedTestData(t)
ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey ctx, k, storeKey := tk.ctx, tk.keeper, tk.storeKey
require.NotPanics(t, func() { require.NotPanics(t, func() {

View File

@ -0,0 +1,41 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// IsSendEnabledCoins uses the parent x/bank keeper to check the coins provided
// and returns an ErrSendDisabled if any of the coins are not configured for
// sending. Returns nil if sending is enabled for all provided coin
func (k Keeper) IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error {
panic("unimplemented")
}
func (k Keeper) SendCoins(
ctx sdk.Context,
from, to sdk.AccAddress,
amt sdk.Coins,
) error {
// IsSendEnabledCoins() is only used in x/bank in msg server, not in keeper,
// so we should also not use it here to align with x/bank behavior.
panic("unimplemented")
}
func (k Keeper) SendCoinsFromAccountToModule(
ctx sdk.Context,
senderAddr sdk.AccAddress,
recipientModule string,
amt sdk.Coins,
) error {
panic("unimplemented")
}
func (k Keeper) SendCoinsFromModuleToAccount(
ctx sdk.Context,
senderModule string,
recipientAddr sdk.AccAddress,
amt sdk.Coins,
) error {
panic("unimplemented")
}

View File

@ -0,0 +1,37 @@
package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/precisebank/types"
)
// GetBalance returns the balance of a specific denom for an address. This will
// return the extended balance for the ExtendedCoinDenom, and the regular
// balance for all other denoms.
func (k Keeper) GetBalance(
ctx sdk.Context,
addr sdk.AccAddress,
denom string,
) sdk.Coin {
// Pass through to x/bank for denoms except ExtendedCoinDenom
if denom != types.ExtendedCoinDenom {
return k.bk.GetBalance(ctx, addr, denom)
}
// x/bank for integer balance - spendable balance only
spendableCoins := k.bk.SpendableCoins(ctx, addr)
integerAmount := spendableCoins.AmountOf(types.IntegerCoinDenom)
// x/precisebank for fractional balance
fractionalAmount, found := k.GetFractionalBalance(ctx, addr)
if !found {
fractionalAmount = sdk.ZeroInt()
}
// (Integer * ConversionFactor) + Fractional
fullAmount := integerAmount.
Mul(types.ConversionFactor()).
Add(fractionalAmount)
return sdk.NewCoin(types.ExtendedCoinDenom, fullAmount)
}

View File

@ -0,0 +1,117 @@
package keeper_test
import (
"testing"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/precisebank/types"
"github.com/stretchr/testify/require"
)
func TestKeeper_GetBalance(t *testing.T) {
tests := []struct {
name string
giveDenom string // queried denom for balance
giveBankBal sdk.Coins // mocked bank balance for giveAddr
giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr
wantBal sdk.Coin
}{
{
"extended denom - no fractional balance",
types.ExtendedCoinDenom,
// queried bank balance in ukava when querying for akava
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
sdkmath.ZeroInt(),
// integer + fractional
sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_000)),
},
{
"extended denom - with fractional balance",
types.ExtendedCoinDenom,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
sdkmath.NewInt(100),
// integer + fractional
sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_000_000_000_100)),
},
{
"extended denom - only fractional balance",
types.ExtendedCoinDenom,
// no coins in bank, only fractional balance
sdk.NewCoins(),
sdkmath.NewInt(100),
sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(100)),
},
{
"extended denom - max fractional balance",
types.ExtendedCoinDenom,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
types.ConversionFactor().SubRaw(1),
// integer + fractional
sdk.NewCoin(types.ExtendedCoinDenom, sdk.NewInt(1000_999_999_999_999)),
},
{
"non-extended denom - ukava returns ukava",
types.IntegerCoinDenom,
sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
sdk.ZeroInt(),
sdk.NewCoin("ukava", sdk.NewInt(1000)),
},
{
"non-extended denom - unaffected by fractional balance",
"ukava",
sdk.NewCoins(sdk.NewCoin("ukava", sdk.NewInt(1000))),
sdkmath.NewInt(100),
sdk.NewCoin("ukava", sdk.NewInt(1000)),
},
{
"unrelated denom - no fractional",
"busd",
sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))),
sdk.ZeroInt(),
sdk.NewCoin("busd", sdk.NewInt(1000)),
},
{
"unrelated denom - unaffected by fractional balance",
"busd",
sdk.NewCoins(sdk.NewCoin("busd", sdk.NewInt(1000))),
sdkmath.NewInt(100),
sdk.NewCoin("busd", sdk.NewInt(1000)),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tk := NewMockedTestData(t)
addr := sdk.AccAddress([]byte("test-address"))
// Set fractional balance in store before query
tk.keeper.SetFractionalBalance(tk.ctx, addr, tt.giveFractionalBal)
if tt.giveDenom == types.ExtendedCoinDenom {
// No balance pass through
tk.bk.EXPECT().
SpendableCoins(tk.ctx, addr).
RunAndReturn(func(_ sdk.Context, _ sdk.AccAddress) sdk.Coins {
return tt.giveBankBal
}).
Once()
} else {
// Pass through to x/bank for denoms except ExtendedCoinDenom
tk.bk.EXPECT().
GetBalance(tk.ctx, addr, tt.giveDenom).
RunAndReturn(func(ctx sdk.Context, aa sdk.AccAddress, s string) sdk.Coin {
require.Equal(t, s, tt.giveDenom, "unexpected denom passed to x/bank.GetBalance")
return sdk.NewCoin(tt.giveDenom, tt.giveBankBal.AmountOf(s))
}).
Once()
}
bal := tk.keeper.GetBalance(tk.ctx, addr, tt.giveDenom)
require.Equal(t, tt.wantBal, bal)
})
}
}

View File

@ -3,7 +3,6 @@ package types
import ( import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
) )
// AccountKeeper defines the expected account keeper interface // AccountKeeper defines the expected account keeper interface
@ -15,9 +14,17 @@ type AccountKeeper interface {
// BankKeeper defines the expected bank keeper interface // BankKeeper defines the expected bank keeper interface
type BankKeeper interface { type BankKeeper interface {
evmtypes.BankKeeper IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
GetSupply(ctx sdk.Context, denom string) sdk.Coin GetSupply(ctx sdk.Context, denom string) sdk.Coin
SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
BlockedAddr(addr sdk.AccAddress) bool
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
} }

View File

@ -0,0 +1,191 @@
// Code generated by mockery v2.43.0. DO NOT EDIT.
package mocks
import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
mock "github.com/stretchr/testify/mock"
types "github.com/cosmos/cosmos-sdk/types"
)
// MockAccountKeeper is an autogenerated mock type for the AccountKeeper type
type MockAccountKeeper struct {
mock.Mock
}
type MockAccountKeeper_Expecter struct {
mock *mock.Mock
}
func (_m *MockAccountKeeper) EXPECT() *MockAccountKeeper_Expecter {
return &MockAccountKeeper_Expecter{mock: &_m.Mock}
}
// GetModuleAccount provides a mock function with given fields: ctx, moduleName
func (_m *MockAccountKeeper) GetModuleAccount(ctx types.Context, moduleName string) authtypes.ModuleAccountI {
ret := _m.Called(ctx, moduleName)
if len(ret) == 0 {
panic("no return value specified for GetModuleAccount")
}
var r0 authtypes.ModuleAccountI
if rf, ok := ret.Get(0).(func(types.Context, string) authtypes.ModuleAccountI); ok {
r0 = rf(ctx, moduleName)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(authtypes.ModuleAccountI)
}
}
return r0
}
// MockAccountKeeper_GetModuleAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModuleAccount'
type MockAccountKeeper_GetModuleAccount_Call struct {
*mock.Call
}
// GetModuleAccount is a helper method to define mock.On call
// - ctx types.Context
// - moduleName string
func (_e *MockAccountKeeper_Expecter) GetModuleAccount(ctx interface{}, moduleName interface{}) *MockAccountKeeper_GetModuleAccount_Call {
return &MockAccountKeeper_GetModuleAccount_Call{Call: _e.mock.On("GetModuleAccount", ctx, moduleName)}
}
func (_c *MockAccountKeeper_GetModuleAccount_Call) Run(run func(ctx types.Context, moduleName string)) *MockAccountKeeper_GetModuleAccount_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(string))
})
return _c
}
func (_c *MockAccountKeeper_GetModuleAccount_Call) Return(_a0 authtypes.ModuleAccountI) *MockAccountKeeper_GetModuleAccount_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAccountKeeper_GetModuleAccount_Call) RunAndReturn(run func(types.Context, string) authtypes.ModuleAccountI) *MockAccountKeeper_GetModuleAccount_Call {
_c.Call.Return(run)
return _c
}
// GetModuleAddress provides a mock function with given fields: moduleName
func (_m *MockAccountKeeper) GetModuleAddress(moduleName string) types.AccAddress {
ret := _m.Called(moduleName)
if len(ret) == 0 {
panic("no return value specified for GetModuleAddress")
}
var r0 types.AccAddress
if rf, ok := ret.Get(0).(func(string) types.AccAddress); ok {
r0 = rf(moduleName)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(types.AccAddress)
}
}
return r0
}
// MockAccountKeeper_GetModuleAddress_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModuleAddress'
type MockAccountKeeper_GetModuleAddress_Call struct {
*mock.Call
}
// GetModuleAddress is a helper method to define mock.On call
// - moduleName string
func (_e *MockAccountKeeper_Expecter) GetModuleAddress(moduleName interface{}) *MockAccountKeeper_GetModuleAddress_Call {
return &MockAccountKeeper_GetModuleAddress_Call{Call: _e.mock.On("GetModuleAddress", moduleName)}
}
func (_c *MockAccountKeeper_GetModuleAddress_Call) Run(run func(moduleName string)) *MockAccountKeeper_GetModuleAddress_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockAccountKeeper_GetModuleAddress_Call) Return(_a0 types.AccAddress) *MockAccountKeeper_GetModuleAddress_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockAccountKeeper_GetModuleAddress_Call) RunAndReturn(run func(string) types.AccAddress) *MockAccountKeeper_GetModuleAddress_Call {
_c.Call.Return(run)
return _c
}
// GetSequence provides a mock function with given fields: _a0, _a1
func (_m *MockAccountKeeper) GetSequence(_a0 types.Context, _a1 types.AccAddress) (uint64, error) {
ret := _m.Called(_a0, _a1)
if len(ret) == 0 {
panic("no return value specified for GetSequence")
}
var r0 uint64
var r1 error
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress) (uint64, error)); ok {
return rf(_a0, _a1)
}
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress) uint64); ok {
r0 = rf(_a0, _a1)
} else {
r0 = ret.Get(0).(uint64)
}
if rf, ok := ret.Get(1).(func(types.Context, types.AccAddress) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockAccountKeeper_GetSequence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSequence'
type MockAccountKeeper_GetSequence_Call struct {
*mock.Call
}
// GetSequence is a helper method to define mock.On call
// - _a0 types.Context
// - _a1 types.AccAddress
func (_e *MockAccountKeeper_Expecter) GetSequence(_a0 interface{}, _a1 interface{}) *MockAccountKeeper_GetSequence_Call {
return &MockAccountKeeper_GetSequence_Call{Call: _e.mock.On("GetSequence", _a0, _a1)}
}
func (_c *MockAccountKeeper_GetSequence_Call) Run(run func(_a0 types.Context, _a1 types.AccAddress)) *MockAccountKeeper_GetSequence_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(types.AccAddress))
})
return _c
}
func (_c *MockAccountKeeper_GetSequence_Call) Return(_a0 uint64, _a1 error) *MockAccountKeeper_GetSequence_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *MockAccountKeeper_GetSequence_Call) RunAndReturn(run func(types.Context, types.AccAddress) (uint64, error)) *MockAccountKeeper_GetSequence_Call {
_c.Call.Return(run)
return _c
}
// NewMockAccountKeeper creates a new instance of MockAccountKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockAccountKeeper(t interface {
mock.TestingT
Cleanup(func())
}) *MockAccountKeeper {
mock := &MockAccountKeeper{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -0,0 +1,530 @@
// Code generated by mockery v2.43.0. DO NOT EDIT.
package mocks
import (
mock "github.com/stretchr/testify/mock"
types "github.com/cosmos/cosmos-sdk/types"
)
// MockBankKeeper is an autogenerated mock type for the BankKeeper type
type MockBankKeeper struct {
mock.Mock
}
type MockBankKeeper_Expecter struct {
mock *mock.Mock
}
func (_m *MockBankKeeper) EXPECT() *MockBankKeeper_Expecter {
return &MockBankKeeper_Expecter{mock: &_m.Mock}
}
// BlockedAddr provides a mock function with given fields: addr
func (_m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool {
ret := _m.Called(addr)
if len(ret) == 0 {
panic("no return value specified for BlockedAddr")
}
var r0 bool
if rf, ok := ret.Get(0).(func(types.AccAddress) bool); ok {
r0 = rf(addr)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockBankKeeper_BlockedAddr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockedAddr'
type MockBankKeeper_BlockedAddr_Call struct {
*mock.Call
}
// BlockedAddr is a helper method to define mock.On call
// - addr types.AccAddress
func (_e *MockBankKeeper_Expecter) BlockedAddr(addr interface{}) *MockBankKeeper_BlockedAddr_Call {
return &MockBankKeeper_BlockedAddr_Call{Call: _e.mock.On("BlockedAddr", addr)}
}
func (_c *MockBankKeeper_BlockedAddr_Call) Run(run func(addr types.AccAddress)) *MockBankKeeper_BlockedAddr_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.AccAddress))
})
return _c
}
func (_c *MockBankKeeper_BlockedAddr_Call) Return(_a0 bool) *MockBankKeeper_BlockedAddr_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_BlockedAddr_Call) RunAndReturn(run func(types.AccAddress) bool) *MockBankKeeper_BlockedAddr_Call {
_c.Call.Return(run)
return _c
}
// BurnCoins provides a mock function with given fields: ctx, moduleName, amt
func (_m *MockBankKeeper) BurnCoins(ctx types.Context, moduleName string, amt types.Coins) error {
ret := _m.Called(ctx, moduleName, amt)
if len(ret) == 0 {
panic("no return value specified for BurnCoins")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, string, types.Coins) error); ok {
r0 = rf(ctx, moduleName, amt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_BurnCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BurnCoins'
type MockBankKeeper_BurnCoins_Call struct {
*mock.Call
}
// BurnCoins is a helper method to define mock.On call
// - ctx types.Context
// - moduleName string
// - amt types.Coins
func (_e *MockBankKeeper_Expecter) BurnCoins(ctx interface{}, moduleName interface{}, amt interface{}) *MockBankKeeper_BurnCoins_Call {
return &MockBankKeeper_BurnCoins_Call{Call: _e.mock.On("BurnCoins", ctx, moduleName, amt)}
}
func (_c *MockBankKeeper_BurnCoins_Call) Run(run func(ctx types.Context, moduleName string, amt types.Coins)) *MockBankKeeper_BurnCoins_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(string), args[2].(types.Coins))
})
return _c
}
func (_c *MockBankKeeper_BurnCoins_Call) Return(_a0 error) *MockBankKeeper_BurnCoins_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_BurnCoins_Call) RunAndReturn(run func(types.Context, string, types.Coins) error) *MockBankKeeper_BurnCoins_Call {
_c.Call.Return(run)
return _c
}
// GetBalance provides a mock function with given fields: ctx, addr, denom
func (_m *MockBankKeeper) GetBalance(ctx types.Context, addr types.AccAddress, denom string) types.Coin {
ret := _m.Called(ctx, addr, denom)
if len(ret) == 0 {
panic("no return value specified for GetBalance")
}
var r0 types.Coin
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, string) types.Coin); ok {
r0 = rf(ctx, addr, denom)
} else {
r0 = ret.Get(0).(types.Coin)
}
return r0
}
// MockBankKeeper_GetBalance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBalance'
type MockBankKeeper_GetBalance_Call struct {
*mock.Call
}
// GetBalance is a helper method to define mock.On call
// - ctx types.Context
// - addr types.AccAddress
// - denom string
func (_e *MockBankKeeper_Expecter) GetBalance(ctx interface{}, addr interface{}, denom interface{}) *MockBankKeeper_GetBalance_Call {
return &MockBankKeeper_GetBalance_Call{Call: _e.mock.On("GetBalance", ctx, addr, denom)}
}
func (_c *MockBankKeeper_GetBalance_Call) Run(run func(ctx types.Context, addr types.AccAddress, denom string)) *MockBankKeeper_GetBalance_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(string))
})
return _c
}
func (_c *MockBankKeeper_GetBalance_Call) Return(_a0 types.Coin) *MockBankKeeper_GetBalance_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_GetBalance_Call) RunAndReturn(run func(types.Context, types.AccAddress, string) types.Coin) *MockBankKeeper_GetBalance_Call {
_c.Call.Return(run)
return _c
}
// GetSupply provides a mock function with given fields: ctx, denom
func (_m *MockBankKeeper) GetSupply(ctx types.Context, denom string) types.Coin {
ret := _m.Called(ctx, denom)
if len(ret) == 0 {
panic("no return value specified for GetSupply")
}
var r0 types.Coin
if rf, ok := ret.Get(0).(func(types.Context, string) types.Coin); ok {
r0 = rf(ctx, denom)
} else {
r0 = ret.Get(0).(types.Coin)
}
return r0
}
// MockBankKeeper_GetSupply_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSupply'
type MockBankKeeper_GetSupply_Call struct {
*mock.Call
}
// GetSupply is a helper method to define mock.On call
// - ctx types.Context
// - denom string
func (_e *MockBankKeeper_Expecter) GetSupply(ctx interface{}, denom interface{}) *MockBankKeeper_GetSupply_Call {
return &MockBankKeeper_GetSupply_Call{Call: _e.mock.On("GetSupply", ctx, denom)}
}
func (_c *MockBankKeeper_GetSupply_Call) Run(run func(ctx types.Context, denom string)) *MockBankKeeper_GetSupply_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(string))
})
return _c
}
func (_c *MockBankKeeper_GetSupply_Call) Return(_a0 types.Coin) *MockBankKeeper_GetSupply_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_GetSupply_Call) RunAndReturn(run func(types.Context, string) types.Coin) *MockBankKeeper_GetSupply_Call {
_c.Call.Return(run)
return _c
}
// IsSendEnabledCoins provides a mock function with given fields: ctx, coins
func (_m *MockBankKeeper) IsSendEnabledCoins(ctx types.Context, coins ...types.Coin) error {
_va := make([]interface{}, len(coins))
for _i := range coins {
_va[_i] = coins[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for IsSendEnabledCoins")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, ...types.Coin) error); ok {
r0 = rf(ctx, coins...)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_IsSendEnabledCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsSendEnabledCoins'
type MockBankKeeper_IsSendEnabledCoins_Call struct {
*mock.Call
}
// IsSendEnabledCoins is a helper method to define mock.On call
// - ctx types.Context
// - coins ...types.Coin
func (_e *MockBankKeeper_Expecter) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *MockBankKeeper_IsSendEnabledCoins_Call {
return &MockBankKeeper_IsSendEnabledCoins_Call{Call: _e.mock.On("IsSendEnabledCoins",
append([]interface{}{ctx}, coins...)...)}
}
func (_c *MockBankKeeper_IsSendEnabledCoins_Call) Run(run func(ctx types.Context, coins ...types.Coin)) *MockBankKeeper_IsSendEnabledCoins_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]types.Coin, len(args)-1)
for i, a := range args[1:] {
if a != nil {
variadicArgs[i] = a.(types.Coin)
}
}
run(args[0].(types.Context), variadicArgs...)
})
return _c
}
func (_c *MockBankKeeper_IsSendEnabledCoins_Call) Return(_a0 error) *MockBankKeeper_IsSendEnabledCoins_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_IsSendEnabledCoins_Call) RunAndReturn(run func(types.Context, ...types.Coin) error) *MockBankKeeper_IsSendEnabledCoins_Call {
_c.Call.Return(run)
return _c
}
// MintCoins provides a mock function with given fields: ctx, moduleName, amt
func (_m *MockBankKeeper) MintCoins(ctx types.Context, moduleName string, amt types.Coins) error {
ret := _m.Called(ctx, moduleName, amt)
if len(ret) == 0 {
panic("no return value specified for MintCoins")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, string, types.Coins) error); ok {
r0 = rf(ctx, moduleName, amt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_MintCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MintCoins'
type MockBankKeeper_MintCoins_Call struct {
*mock.Call
}
// MintCoins is a helper method to define mock.On call
// - ctx types.Context
// - moduleName string
// - amt types.Coins
func (_e *MockBankKeeper_Expecter) MintCoins(ctx interface{}, moduleName interface{}, amt interface{}) *MockBankKeeper_MintCoins_Call {
return &MockBankKeeper_MintCoins_Call{Call: _e.mock.On("MintCoins", ctx, moduleName, amt)}
}
func (_c *MockBankKeeper_MintCoins_Call) Run(run func(ctx types.Context, moduleName string, amt types.Coins)) *MockBankKeeper_MintCoins_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(string), args[2].(types.Coins))
})
return _c
}
func (_c *MockBankKeeper_MintCoins_Call) Return(_a0 error) *MockBankKeeper_MintCoins_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_MintCoins_Call) RunAndReturn(run func(types.Context, string, types.Coins) error) *MockBankKeeper_MintCoins_Call {
_c.Call.Return(run)
return _c
}
// SendCoins provides a mock function with given fields: ctx, fromAddr, toAddr, amt
func (_m *MockBankKeeper) SendCoins(ctx types.Context, fromAddr types.AccAddress, toAddr types.AccAddress, amt types.Coins) error {
ret := _m.Called(ctx, fromAddr, toAddr, amt)
if len(ret) == 0 {
panic("no return value specified for SendCoins")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, types.AccAddress, types.Coins) error); ok {
r0 = rf(ctx, fromAddr, toAddr, amt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_SendCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoins'
type MockBankKeeper_SendCoins_Call struct {
*mock.Call
}
// SendCoins is a helper method to define mock.On call
// - ctx types.Context
// - fromAddr types.AccAddress
// - toAddr types.AccAddress
// - amt types.Coins
func (_e *MockBankKeeper_Expecter) SendCoins(ctx interface{}, fromAddr interface{}, toAddr interface{}, amt interface{}) *MockBankKeeper_SendCoins_Call {
return &MockBankKeeper_SendCoins_Call{Call: _e.mock.On("SendCoins", ctx, fromAddr, toAddr, amt)}
}
func (_c *MockBankKeeper_SendCoins_Call) Run(run func(ctx types.Context, fromAddr types.AccAddress, toAddr types.AccAddress, amt types.Coins)) *MockBankKeeper_SendCoins_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(types.AccAddress), args[3].(types.Coins))
})
return _c
}
func (_c *MockBankKeeper_SendCoins_Call) Return(_a0 error) *MockBankKeeper_SendCoins_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_SendCoins_Call) RunAndReturn(run func(types.Context, types.AccAddress, types.AccAddress, types.Coins) error) *MockBankKeeper_SendCoins_Call {
_c.Call.Return(run)
return _c
}
// SendCoinsFromAccountToModule provides a mock function with given fields: ctx, senderAddr, recipientModule, amt
func (_m *MockBankKeeper) SendCoinsFromAccountToModule(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error {
ret := _m.Called(ctx, senderAddr, recipientModule, amt)
if len(ret) == 0 {
panic("no return value specified for SendCoinsFromAccountToModule")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress, string, types.Coins) error); ok {
r0 = rf(ctx, senderAddr, recipientModule, amt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_SendCoinsFromAccountToModule_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromAccountToModule'
type MockBankKeeper_SendCoinsFromAccountToModule_Call struct {
*mock.Call
}
// SendCoinsFromAccountToModule is a helper method to define mock.On call
// - ctx types.Context
// - senderAddr types.AccAddress
// - recipientModule string
// - amt types.Coins
func (_e *MockBankKeeper_Expecter) SendCoinsFromAccountToModule(ctx interface{}, senderAddr interface{}, recipientModule interface{}, amt interface{}) *MockBankKeeper_SendCoinsFromAccountToModule_Call {
return &MockBankKeeper_SendCoinsFromAccountToModule_Call{Call: _e.mock.On("SendCoinsFromAccountToModule", ctx, senderAddr, recipientModule, amt)}
}
func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) Run(run func(ctx types.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins)) *MockBankKeeper_SendCoinsFromAccountToModule_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(types.AccAddress), args[2].(string), args[3].(types.Coins))
})
return _c
}
func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) Return(_a0 error) *MockBankKeeper_SendCoinsFromAccountToModule_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_SendCoinsFromAccountToModule_Call) RunAndReturn(run func(types.Context, types.AccAddress, string, types.Coins) error) *MockBankKeeper_SendCoinsFromAccountToModule_Call {
_c.Call.Return(run)
return _c
}
// SendCoinsFromModuleToAccount provides a mock function with given fields: ctx, senderModule, recipientAddr, amt
func (_m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error {
ret := _m.Called(ctx, senderModule, recipientAddr, amt)
if len(ret) == 0 {
panic("no return value specified for SendCoinsFromModuleToAccount")
}
var r0 error
if rf, ok := ret.Get(0).(func(types.Context, string, types.AccAddress, types.Coins) error); ok {
r0 = rf(ctx, senderModule, recipientAddr, amt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockBankKeeper_SendCoinsFromModuleToAccount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromModuleToAccount'
type MockBankKeeper_SendCoinsFromModuleToAccount_Call struct {
*mock.Call
}
// SendCoinsFromModuleToAccount is a helper method to define mock.On call
// - ctx types.Context
// - senderModule string
// - recipientAddr types.AccAddress
// - amt types.Coins
func (_e *MockBankKeeper_Expecter) SendCoinsFromModuleToAccount(ctx interface{}, senderModule interface{}, recipientAddr interface{}, amt interface{}) *MockBankKeeper_SendCoinsFromModuleToAccount_Call {
return &MockBankKeeper_SendCoinsFromModuleToAccount_Call{Call: _e.mock.On("SendCoinsFromModuleToAccount", ctx, senderModule, recipientAddr, amt)}
}
func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) Run(run func(ctx types.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins)) *MockBankKeeper_SendCoinsFromModuleToAccount_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(string), args[2].(types.AccAddress), args[3].(types.Coins))
})
return _c
}
func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) Return(_a0 error) *MockBankKeeper_SendCoinsFromModuleToAccount_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_SendCoinsFromModuleToAccount_Call) RunAndReturn(run func(types.Context, string, types.AccAddress, types.Coins) error) *MockBankKeeper_SendCoinsFromModuleToAccount_Call {
_c.Call.Return(run)
return _c
}
// SpendableCoins provides a mock function with given fields: ctx, addr
func (_m *MockBankKeeper) SpendableCoins(ctx types.Context, addr types.AccAddress) types.Coins {
ret := _m.Called(ctx, addr)
if len(ret) == 0 {
panic("no return value specified for SpendableCoins")
}
var r0 types.Coins
if rf, ok := ret.Get(0).(func(types.Context, types.AccAddress) types.Coins); ok {
r0 = rf(ctx, addr)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(types.Coins)
}
}
return r0
}
// MockBankKeeper_SpendableCoins_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SpendableCoins'
type MockBankKeeper_SpendableCoins_Call struct {
*mock.Call
}
// SpendableCoins is a helper method to define mock.On call
// - ctx types.Context
// - addr types.AccAddress
func (_e *MockBankKeeper_Expecter) SpendableCoins(ctx interface{}, addr interface{}) *MockBankKeeper_SpendableCoins_Call {
return &MockBankKeeper_SpendableCoins_Call{Call: _e.mock.On("SpendableCoins", ctx, addr)}
}
func (_c *MockBankKeeper_SpendableCoins_Call) Run(run func(ctx types.Context, addr types.AccAddress)) *MockBankKeeper_SpendableCoins_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(types.Context), args[1].(types.AccAddress))
})
return _c
}
func (_c *MockBankKeeper_SpendableCoins_Call) Return(_a0 types.Coins) *MockBankKeeper_SpendableCoins_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *MockBankKeeper_SpendableCoins_Call) RunAndReturn(run func(types.Context, types.AccAddress) types.Coins) *MockBankKeeper_SpendableCoins_Call {
_c.Call.Return(run)
return _c
}
// NewMockBankKeeper creates a new instance of MockBankKeeper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockBankKeeper(t interface {
mock.TestingT
Cleanup(func())
}) *MockBankKeeper {
mock := &MockBankKeeper{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}