2019-12-03 14:33:20 +00:00
package app
import (
2022-01-08 00:39:27 +00:00
"encoding/json"
2019-12-03 14:33:20 +00:00
"math/rand"
2019-12-05 13:51:46 +00:00
"testing"
2020-08-17 15:06:59 +00:00
"time"
2019-12-05 13:51:46 +00:00
2022-01-08 00:39:27 +00:00
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
2022-12-09 21:24:35 +00:00
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
2022-01-08 00:39:27 +00:00
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
distkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
2022-12-09 21:24:35 +00:00
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
2019-12-05 13:51:46 +00:00
"github.com/stretchr/testify/require"
2019-12-03 14:33:20 +00:00
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
2022-01-08 00:39:27 +00:00
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
2022-04-21 20:16:28 +00:00
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
2022-08-23 17:04:40 +00:00
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
2019-12-03 14:33:20 +00:00
2022-01-08 00:39:27 +00:00
auctionkeeper "github.com/kava-labs/kava/x/auction/keeper"
bep3keeper "github.com/kava-labs/kava/x/bep3/keeper"
cdpkeeper "github.com/kava-labs/kava/x/cdp/keeper"
committeekeeper "github.com/kava-labs/kava/x/committee/keeper"
2022-12-09 21:24:35 +00:00
communitykeeper "github.com/kava-labs/kava/x/community/keeper"
2022-07-20 23:14:43 +00:00
earnkeeper "github.com/kava-labs/kava/x/earn/keeper"
2022-04-21 20:16:28 +00:00
evmutilkeeper "github.com/kava-labs/kava/x/evmutil/keeper"
hardkeeper "github.com/kava-labs/kava/x/hard/keeper"
2022-01-08 00:39:27 +00:00
incentivekeeper "github.com/kava-labs/kava/x/incentive/keeper"
issuancekeeper "github.com/kava-labs/kava/x/issuance/keeper"
kavadistkeeper "github.com/kava-labs/kava/x/kavadist/keeper"
2022-12-09 21:24:35 +00:00
kavamintkeeper "github.com/kava-labs/kava/x/kavamint/keeper"
2022-12-09 22:31:31 +00:00
kavaminttypes "github.com/kava-labs/kava/x/kavamint/types"
2022-09-15 22:00:32 +00:00
liquidkeeper "github.com/kava-labs/kava/x/liquid/keeper"
2022-01-08 00:39:27 +00:00
pricefeedkeeper "github.com/kava-labs/kava/x/pricefeed/keeper"
2022-09-28 02:28:57 +00:00
routerkeeper "github.com/kava-labs/kava/x/router/keeper"
2022-03-22 21:13:27 +00:00
savingskeeper "github.com/kava-labs/kava/x/savings/keeper"
2022-01-08 00:39:27 +00:00
swapkeeper "github.com/kava-labs/kava/x/swap/keeper"
2019-12-03 14:33:20 +00:00
)
2021-06-10 13:35:44 +00:00
var (
2022-06-06 16:07:31 +00:00
emptyTime time . Time
testChainID = "kavatest_1-1"
defaultInitialHeight int64 = 1
2021-06-10 13:35:44 +00:00
)
2019-12-03 14:33:20 +00:00
// TestApp is a simple wrapper around an App. It exposes internal keepers for use in integration tests.
// This file also contains test helpers. Ideally they would be in separate package.
// Basic Usage:
2022-12-22 01:08:16 +00:00
// Create a test app with NewTestApp, then all keepers and their methods can be accessed for test setup and execution.
2019-12-03 14:33:20 +00:00
// Advanced Usage:
2022-12-22 01:08:16 +00:00
// Some tests call for an app to be initialized with some state. This can be achieved through keeper method calls (ie keeper.SetParams(...)).
// However this leads to a lot of duplicated logic similar to InitGenesis methods.
// So TestApp.InitializeFromGenesisStates() will call InitGenesis with the default genesis state.
2019-12-03 14:35:27 +00:00
// and TestApp.InitializeFromGenesisStates(authState, cdpState) will do the same but overwrite the auth and cdp sections of the default genesis state
2022-12-22 01:08:16 +00:00
// Creating the genesis states can be combersome, but helper methods can make it easier such as NewAuthGenStateFromAccounts below.
2019-12-03 14:33:20 +00:00
type TestApp struct {
App
}
2022-01-08 00:39:27 +00:00
// NewTestApp creates a new TestApp
//
// Note, it also sets the sdk config with the app's address prefix, coin type, etc.
2019-12-03 14:33:20 +00:00
func NewTestApp ( ) TestApp {
2022-01-08 00:39:27 +00:00
SetSDKConfig ( )
2020-04-23 16:35:58 +00:00
2022-01-08 00:39:27 +00:00
return NewTestAppFromSealed ( )
2019-12-03 14:33:20 +00:00
}
2022-01-08 00:39:27 +00:00
// NewTestAppFromSealed creates a TestApp without first setting sdk config.
2021-08-26 22:53:46 +00:00
func NewTestAppFromSealed ( ) TestApp {
db := tmdb . NewMemDB ( )
2022-01-08 00:39:27 +00:00
encCfg := MakeEncodingConfig ( )
2022-04-21 20:16:28 +00:00
app := NewApp ( log . NewNopLogger ( ) , db , DefaultNodeHome , nil , encCfg , DefaultOptions )
2021-08-26 22:53:46 +00:00
return TestApp { App : * app }
}
2020-05-07 20:34:05 +00:00
// nolint
2022-01-08 00:39:27 +00:00
func ( tApp TestApp ) GetAccountKeeper ( ) authkeeper . AccountKeeper { return tApp . accountKeeper }
func ( tApp TestApp ) GetBankKeeper ( ) bankkeeper . Keeper { return tApp . bankKeeper }
func ( tApp TestApp ) GetStakingKeeper ( ) stakingkeeper . Keeper { return tApp . stakingKeeper }
func ( tApp TestApp ) GetSlashingKeeper ( ) slashingkeeper . Keeper { return tApp . slashingKeeper }
func ( tApp TestApp ) GetDistrKeeper ( ) distkeeper . Keeper { return tApp . distrKeeper }
func ( tApp TestApp ) GetGovKeeper ( ) govkeeper . Keeper { return tApp . govKeeper }
func ( tApp TestApp ) GetCrisisKeeper ( ) crisiskeeper . Keeper { return tApp . crisisKeeper }
func ( tApp TestApp ) GetParamsKeeper ( ) paramskeeper . Keeper { return tApp . paramsKeeper }
func ( tApp TestApp ) GetKavadistKeeper ( ) kavadistkeeper . Keeper { return tApp . kavadistKeeper }
func ( tApp TestApp ) GetAuctionKeeper ( ) auctionkeeper . Keeper { return tApp . auctionKeeper }
func ( tApp TestApp ) GetIssuanceKeeper ( ) issuancekeeper . Keeper { return tApp . issuanceKeeper }
func ( tApp TestApp ) GetBep3Keeper ( ) bep3keeper . Keeper { return tApp . bep3Keeper }
func ( tApp TestApp ) GetPriceFeedKeeper ( ) pricefeedkeeper . Keeper { return tApp . pricefeedKeeper }
func ( tApp TestApp ) GetSwapKeeper ( ) swapkeeper . Keeper { return tApp . swapKeeper }
func ( tApp TestApp ) GetCDPKeeper ( ) cdpkeeper . Keeper { return tApp . cdpKeeper }
func ( tApp TestApp ) GetHardKeeper ( ) hardkeeper . Keeper { return tApp . hardKeeper }
func ( tApp TestApp ) GetCommitteeKeeper ( ) committeekeeper . Keeper { return tApp . committeeKeeper }
func ( tApp TestApp ) GetIncentiveKeeper ( ) incentivekeeper . Keeper { return tApp . incentiveKeeper }
2022-04-21 20:16:28 +00:00
func ( tApp TestApp ) GetEvmutilKeeper ( ) evmutilkeeper . Keeper { return tApp . evmutilKeeper }
func ( tApp TestApp ) GetEvmKeeper ( ) * evmkeeper . Keeper { return tApp . evmKeeper }
2022-03-22 21:13:27 +00:00
func ( tApp TestApp ) GetSavingsKeeper ( ) savingskeeper . Keeper { return tApp . savingsKeeper }
2022-08-23 17:04:40 +00:00
func ( tApp TestApp ) GetFeeMarketKeeper ( ) feemarketkeeper . Keeper { return tApp . feeMarketKeeper }
2022-09-15 22:00:32 +00:00
func ( tApp TestApp ) GetLiquidKeeper ( ) liquidkeeper . Keeper { return tApp . liquidKeeper }
2022-07-20 23:14:43 +00:00
func ( tApp TestApp ) GetEarnKeeper ( ) earnkeeper . Keeper { return tApp . earnKeeper }
2022-09-28 02:28:57 +00:00
func ( tApp TestApp ) GetRouterKeeper ( ) routerkeeper . Keeper { return tApp . routerKeeper }
2022-12-09 21:24:35 +00:00
func ( tApp TestApp ) GetKavamintKeeper ( ) kavamintkeeper . Keeper { return tApp . kavamintKeeper }
func ( tApp TestApp ) GetCommunityKeeper ( ) communitykeeper . Keeper { return tApp . communityKeeper }
2022-01-08 00:39:27 +00:00
// LegacyAmino returns the app's amino codec.
func ( app * App ) LegacyAmino ( ) * codec . LegacyAmino {
return app . legacyAmino
}
// AppCodec returns the app's app codec.
func ( app * App ) AppCodec ( ) codec . Codec {
return app . appCodec
}
2019-12-03 14:33:20 +00:00
2022-06-06 16:07:31 +00:00
// InitializeFromGenesisStates calls InitChain on the app using the provided genesis states.
// If any module genesis states are missing, defaults are used.
2019-12-03 14:33:20 +00:00
func ( tApp TestApp ) InitializeFromGenesisStates ( genesisStates ... GenesisState ) TestApp {
2022-06-06 16:07:31 +00:00
return tApp . InitializeFromGenesisStatesWithTimeAndChainIDAndHeight ( emptyTime , testChainID , defaultInitialHeight , genesisStates ... )
2019-12-03 14:33:20 +00:00
}
2022-06-06 16:07:31 +00:00
// InitializeFromGenesisStatesWithTime calls InitChain on the app using the provided genesis states and time.
// If any module genesis states are missing, defaults are used.
2020-08-17 15:06:59 +00:00
func ( tApp TestApp ) InitializeFromGenesisStatesWithTime ( genTime time . Time , genesisStates ... GenesisState ) TestApp {
2022-06-06 16:07:31 +00:00
return tApp . InitializeFromGenesisStatesWithTimeAndChainIDAndHeight ( genTime , testChainID , defaultInitialHeight , genesisStates ... )
2020-08-17 15:06:59 +00:00
}
2022-06-06 16:07:31 +00:00
// InitializeFromGenesisStatesWithTimeAndChainID calls InitChain on the app using the provided genesis states, time, and chain id.
// If any module genesis states are missing, defaults are used.
2020-10-06 18:25:05 +00:00
func ( tApp TestApp ) InitializeFromGenesisStatesWithTimeAndChainID ( genTime time . Time , chainID string , genesisStates ... GenesisState ) TestApp {
2022-06-06 16:07:31 +00:00
return tApp . InitializeFromGenesisStatesWithTimeAndChainIDAndHeight ( genTime , chainID , defaultInitialHeight , genesisStates ... )
}
// InitializeFromGenesisStatesWithTimeAndChainIDAndHeight calls InitChain on the app using the provided genesis states and other parameters.
// If any module genesis states are missing, defaults are used.
func ( tApp TestApp ) InitializeFromGenesisStatesWithTimeAndChainIDAndHeight ( genTime time . Time , chainID string , initialHeight int64 , genesisStates ... GenesisState ) TestApp {
2020-10-06 18:25:05 +00:00
// Create a default genesis state and overwrite with provided values
genesisState := NewDefaultGenesisState ( )
for _ , state := range genesisStates {
for k , v := range state {
genesisState [ k ] = v
}
}
// Initialize the chain
2022-01-08 00:39:27 +00:00
stateBytes , err := json . Marshal ( genesisState )
2020-10-06 18:25:05 +00:00
if err != nil {
panic ( err )
}
tApp . InitChain (
abci . RequestInitChain {
Time : genTime ,
Validators : [ ] abci . ValidatorUpdate { } ,
AppStateBytes : stateBytes ,
ChainId : chainID ,
2022-04-21 20:16:28 +00:00
// Set consensus params, which is needed by x/feemarket
ConsensusParams : & abci . ConsensusParams {
Block : & abci . BlockParams {
MaxBytes : 200000 ,
MaxGas : 20000000 ,
} ,
} ,
2022-06-06 16:07:31 +00:00
InitialHeight : initialHeight ,
2020-10-06 18:25:05 +00:00
} ,
)
tApp . Commit ( )
2022-04-21 20:16:28 +00:00
tApp . BeginBlock ( abci . RequestBeginBlock {
Header : tmproto . Header {
Height : tApp . LastBlockHeight ( ) + 1 , Time : genTime , ChainID : chainID ,
} ,
} )
2020-10-06 18:25:05 +00:00
return tApp
}
2022-01-08 00:39:27 +00:00
// CheckBalance requires the account address has the expected amount of coins.
2019-12-05 13:51:46 +00:00
func ( tApp TestApp ) CheckBalance ( t * testing . T , ctx sdk . Context , owner sdk . AccAddress , expectedCoins sdk . Coins ) {
2022-01-08 00:39:27 +00:00
coins := tApp . GetBankKeeper ( ) . GetAllBalances ( ctx , owner )
require . Equal ( t , expectedCoins , coins )
}
2022-12-09 21:24:35 +00:00
// GetModuleAccountBalance gets the current balance of the denom for a module account
func ( tApp TestApp ) GetModuleAccountBalance ( ctx sdk . Context , moduleName string , denom string ) sdk . Int {
moduleAcc := tApp . accountKeeper . GetModuleAccount ( ctx , moduleName )
balance := tApp . bankKeeper . GetBalance ( ctx , moduleAcc . GetAddress ( ) , denom )
return balance . Amount
}
2022-01-08 00:39:27 +00:00
// FundAccount is a utility function that funds an account by minting and sending the coins to the address.
func ( tApp TestApp ) FundAccount ( ctx sdk . Context , addr sdk . AccAddress , amounts sdk . Coins ) error {
2022-12-09 22:31:31 +00:00
if err := tApp . bankKeeper . MintCoins ( ctx , kavaminttypes . ModuleAccountName , amounts ) ; err != nil {
2022-01-08 00:39:27 +00:00
return err
}
2022-12-09 22:31:31 +00:00
return tApp . bankKeeper . SendCoinsFromModuleToAccount ( ctx , kavaminttypes . ModuleAccountName , addr , amounts )
2022-01-08 00:39:27 +00:00
}
// NewQueryServerTestHelper creates a new QueryServiceTestHelper that wraps the provided sdk.Context.
func ( tApp TestApp ) NewQueryServerTestHelper ( ctx sdk . Context ) * baseapp . QueryServiceTestHelper {
return baseapp . NewQueryServerTestHelper ( ctx , tApp . interfaceRegistry )
}
// FundModuleAccount is a utility function that funds a module account by minting and sending the coins to the address.
func ( tApp TestApp ) FundModuleAccount ( ctx sdk . Context , recipientMod string , amounts sdk . Coins ) error {
2022-12-09 22:31:31 +00:00
if err := tApp . bankKeeper . MintCoins ( ctx , kavaminttypes . ModuleAccountName , amounts ) ; err != nil {
2022-01-08 00:39:27 +00:00
return err
}
2022-12-09 22:31:31 +00:00
return tApp . bankKeeper . SendCoinsFromModuleToModule ( ctx , kavaminttypes . ModuleAccountName , recipientMod , amounts )
2019-12-05 13:51:46 +00:00
}
2022-12-09 21:24:35 +00:00
// CreateNewUnbondedValidator creates a new validator in the staking module.
// New validators are unbonded until the end blocker is run.
func ( tApp TestApp ) CreateNewUnbondedValidator ( ctx sdk . Context , valAddress sdk . ValAddress , selfDelegation sdk . Int ) error {
msg , err := stakingtypes . NewMsgCreateValidator (
valAddress ,
ed25519 . GenPrivKey ( ) . PubKey ( ) ,
sdk . NewCoin ( tApp . stakingKeeper . BondDenom ( ctx ) , selfDelegation ) ,
stakingtypes . Description { } ,
stakingtypes . NewCommissionRates ( sdk . ZeroDec ( ) , sdk . ZeroDec ( ) , sdk . ZeroDec ( ) ) ,
sdk . NewInt ( 1e6 ) ,
)
if err != nil {
return err
}
msgServer := stakingkeeper . NewMsgServerImpl ( tApp . stakingKeeper )
_ , err = msgServer . CreateValidator ( sdk . WrapSDKContext ( ctx ) , msg )
return err
}
2022-01-08 00:39:27 +00:00
// GeneratePrivKeyAddressPairsFromRand generates (deterministically) a total of n private keys and addresses.
func GeneratePrivKeyAddressPairs ( n int ) ( keys [ ] cryptotypes . PrivKey , addrs [ ] sdk . AccAddress ) {
2019-12-03 14:33:20 +00:00
r := rand . New ( rand . NewSource ( 12345 ) ) // make the generation deterministic
2022-01-08 00:39:27 +00:00
keys = make ( [ ] cryptotypes . PrivKey , n )
2019-12-03 14:33:20 +00:00
addrs = make ( [ ] sdk . AccAddress , n )
for i := 0 ; i < n ; i ++ {
secret := make ( [ ] byte , 32 )
_ , err := r . Read ( secret )
if err != nil {
panic ( "Could not read randomness" )
}
2022-01-08 00:39:27 +00:00
keys [ i ] = secp256k1 . GenPrivKeyFromSecret ( secret )
2019-12-03 14:33:20 +00:00
addrs [ i ] = sdk . AccAddress ( keys [ i ] . PubKey ( ) . Address ( ) )
}
return
}
2021-06-10 13:35:44 +00:00
2022-10-19 19:26:14 +00:00
// RandomAddress non-deterministically generates a new address, discarding the private key.
func RandomAddress ( ) sdk . AccAddress {
secret := make ( [ ] byte , 32 )
_ , err := rand . Read ( secret )
if err != nil {
panic ( "Could not read randomness" )
}
key := secp256k1 . GenPrivKeyFromSecret ( secret )
return sdk . AccAddress ( key . PubKey ( ) . Address ( ) )
}
2022-01-08 00:39:27 +00:00
// NewFundedGenStateWithSameCoins creates a (auth and bank) genesis state populated with accounts from the given addresses and balance.
func NewFundedGenStateWithSameCoins ( cdc codec . JSONCodec , balance sdk . Coins , addresses [ ] sdk . AccAddress ) GenesisState {
builder := NewAuthBankGenesisBuilder ( )
for _ , address := range addresses {
builder . WithSimpleAccount ( address , balance )
2021-06-10 13:35:44 +00:00
}
2022-01-08 00:39:27 +00:00
return builder . BuildMarshalled ( cdc )
2021-06-10 13:35:44 +00:00
}
2022-01-08 00:39:27 +00:00
// NewFundedGenStateWithCoins creates a (auth and bank) genesis state populated with accounts from the given addresses and coins.
func NewFundedGenStateWithCoins ( cdc codec . JSONCodec , coins [ ] sdk . Coins , addresses [ ] sdk . AccAddress ) GenesisState {
builder := NewAuthBankGenesisBuilder ( )
for i , address := range addresses {
builder . WithSimpleAccount ( address , coins [ i ] )
2021-06-10 13:35:44 +00:00
}
2022-01-08 00:39:27 +00:00
return builder . BuildMarshalled ( cdc )
2021-06-10 13:35:44 +00:00
}
2022-01-08 00:39:27 +00:00
// NewFundedGenStateWithSameCoinsWithModuleAccount creates a (auth and bank) genesis state populated with accounts from the given addresses and balance along with an empty module account
func NewFundedGenStateWithSameCoinsWithModuleAccount ( cdc codec . JSONCodec , coins sdk . Coins , addresses [ ] sdk . AccAddress , modAcc * authtypes . ModuleAccount ) GenesisState {
builder := NewAuthBankGenesisBuilder ( )
2021-06-10 13:35:44 +00:00
2022-01-08 00:39:27 +00:00
for _ , address := range addresses {
builder . WithSimpleAccount ( address , coins )
2021-06-10 13:35:44 +00:00
}
2022-01-08 00:39:27 +00:00
builder . WithSimpleModuleAccount ( modAcc . Address , nil )
2021-06-10 13:35:44 +00:00
2022-01-08 00:39:27 +00:00
return builder . BuildMarshalled ( cdc )
2021-06-10 13:35:44 +00:00
}