From df41b6563c5ffcd451a3864ba55febdcf9987a7b Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Tue, 14 Jun 2022 08:32:12 +0200 Subject: [PATCH] feat: decouple `x/nft` from simapp (#12233) --- CHANGELOG.md | 1 + simapp/test_helpers.go | 140 ++------------------- testutil/network/network.go | 19 ++- testutil/sims/address_helpers.go | 96 +++++++++++++++ testutil/sims/app_helpers.go | 184 ++++++++++++++++++++++++++++ testutil/sims/helpers.go | 27 ---- x/nft/client/testutil/cli_test.go | 1 - x/nft/keeper/grpc_query_test.go | 8 +- x/nft/keeper/keeper_test.go | 125 +++++++++++-------- x/nft/module/module.go | 8 +- x/nft/simulation/decoder_test.go | 7 +- x/nft/simulation/genesis_test.go | 9 +- x/nft/simulation/operations.go | 4 +- x/nft/simulation/operations_test.go | 60 ++++++--- x/nft/spec/01_concepts.md | 6 + x/nft/testutil/app.yaml | 22 ++-- x/nft/testutil/app_config.go | 8 ++ 17 files changed, 469 insertions(+), 256 deletions(-) create mode 100644 testutil/sims/address_helpers.go create mode 100644 testutil/sims/app_helpers.go delete mode 100644 testutil/sims/helpers.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c23171c31fa..968f73d40b1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (testutil) [#12233](https://github.com/cosmos/cosmos-sdk/pull/12233) Move `simapp.TestAddr` to `simtestutil.TestAddr` (`testutil/sims`) * (x/staking) [#12102](https://github.com/cosmos/cosmos-sdk/pull/12102) Staking keeper now is passed by reference instead of copy. Keeper's SetHooks no longer returns keeper. It updates the keeper in place instead. * (linting) [#12141](https://github.com/cosmos/cosmos-sdk/pull/12141) Fix usability related linting for database. This means removing the infix Prefix from `prefix.NewPrefixWriter` and such so that it is `prefix.NewWriter` and making `db.DBConnection` and such into `db.Connection` diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index a12eff5ddab3..c3cefdc520ca 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -5,10 +5,8 @@ import ( "context" "encoding/hex" "encoding/json" - "fmt" "strconv" "testing" - "time" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" @@ -21,8 +19,6 @@ import ( "cosmossdk.io/math" bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -38,7 +34,6 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) // SetupOptions defines arguments that are passed into `Simapp` constructor. @@ -83,7 +78,8 @@ func NewSimappWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptio app := NewSimApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts) genesisState := NewDefaultGenesisState(app.appCodec) - genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance) + genesisState, err = simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, []authtypes.GenesisAccount{acc}, balance) + require.NoError(t, err) if !isCheckTx { // init chain must be called to stop deliverState from being nil @@ -128,70 +124,6 @@ func Setup(t *testing.T, isCheckTx bool) *SimApp { return app } -func genesisStateWithValSet(t *testing.T, - app *SimApp, genesisState GenesisState, - valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, - balances ...banktypes.Balance, -) GenesisState { - // set genesis accounts - authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) - genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) - - validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) - delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - - bondAmt := sdk.DefaultPowerReduction - - for _, val := range valSet.Validators { - pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) - require.NoError(t, err) - pkAny, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) - validator := stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(val.Address).String(), - ConsensusPubkey: pkAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: bondAmt, - DelegatorShares: sdk.OneDec(), - Description: stakingtypes.Description{}, - UnbondingHeight: int64(0), - UnbondingTime: time.Unix(0, 0).UTC(), - Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), - MinSelfDelegation: sdk.ZeroInt(), - } - validators = append(validators, validator) - delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) - - } - // set validators and delegations - stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) - genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis) - - totalSupply := sdk.NewCoins() - for _, b := range balances { - // add genesis acc tokens to total supply - totalSupply = totalSupply.Add(b.Coins...) - } - - for range delegations { - // add delegated tokens to total supply - totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)) - } - - // add bonded amount to bonded pool module account - balances = append(balances, banktypes.Balance{ - Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, - }) - - // update total supply - bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{}) - genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) - - return genesisState -} - // SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts // that also act as delegators. For simplicity, each validator is bonded with a delegation // of one consensus engine unit in the default token of the simapp from first genesis @@ -200,7 +132,8 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs t.Helper() app, genesisState := setup(true, 5) - genesisState = genesisStateWithValSet(t, app, genesisState, valSet, genAccs, balances...) + genesisState, err := simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, genAccs, balances...) + require.NoError(t, err) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) @@ -266,46 +199,12 @@ func GenesisStateWithSingleValidator(t *testing.T, app *SimApp) GenesisState { } genesisState := NewDefaultGenesisState(app.appCodec) - genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balances...) + genesisState, err = simtestutil.GenesisStateWithValSet(app.AppCodec(), genesisState, valSet, []authtypes.GenesisAccount{acc}, balances...) + require.NoError(t, err) return genesisState } -type GenerateAccountStrategy func(int) []sdk.AccAddress - -// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order. -func createRandomAccounts(accNum int) []sdk.AccAddress { - testAddrs := make([]sdk.AccAddress, accNum) - for i := 0; i < accNum; i++ { - pk := ed25519.GenPrivKey().PubKey() - testAddrs[i] = sdk.AccAddress(pk.Address()) - } - - return testAddrs -} - -// createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order. -func createIncrementalAccounts(accNum int) []sdk.AccAddress { - var addresses []sdk.AccAddress - var buffer bytes.Buffer - - // start at 100 so we can make up to 999 test addresses with valid test addresses - for i := 100; i < (accNum + 100); i++ { - numString := strconv.Itoa(i) - buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string - - buffer.WriteString(numString) // adding on final two digits to make addresses unique - res, _ := sdk.AccAddressFromHexUnsafe(buffer.String()) - bech := res.String() - addr, _ := TestAddr(buffer.String(), bech) - - addresses = append(addresses, addr) - buffer.Reset() - } - - return addresses -} - // AddTestAddrsFromPubKeys adds the addresses into the SimApp providing only the public keys. func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes.PubKey, accAmt math.Int) { initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) @@ -318,16 +217,16 @@ func AddTestAddrsFromPubKeys(app *SimApp, ctx sdk.Context, pubKeys []cryptotypes // AddTestAddrs constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order func AddTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { - return addTestAddrs(app, ctx, accNum, accAmt, createRandomAccounts) + return addTestAddrs(app, ctx, accNum, accAmt, simtestutil.CreateRandomAccounts) } // AddTestAddrsIncremental constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order func AddTestAddrsIncremental(app *SimApp, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { - return addTestAddrs(app, ctx, accNum, accAmt, createIncrementalAccounts) + return addTestAddrs(app, ctx, accNum, accAmt, simtestutil.CreateIncrementalAccounts) } -func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { +func addTestAddrs(app *SimApp, ctx sdk.Context, accNum int, accAmt math.Int, strategy simtestutil.GenerateAccountStrategy) []sdk.AccAddress { testAddrs := strategy(accNum) initCoins := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), accAmt)) @@ -362,27 +261,6 @@ func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress { return valAddrs } -func TestAddr(addr string, bech string) (sdk.AccAddress, error) { - res, err := sdk.AccAddressFromHexUnsafe(addr) - if err != nil { - return nil, err - } - bechexpected := res.String() - if bech != bechexpected { - return nil, fmt.Errorf("bech encoding doesn't match reference") - } - - bechres, err := sdk.AccAddressFromBech32(bech) - if err != nil { - return nil, err - } - if !bytes.Equal(bechres, res) { - return nil, err - } - - return res, nil -} - // CheckBalance checks the balance of an account. func CheckBalance(t *testing.T, app *SimApp, addr sdk.AccAddress, balances sdk.Coins) { ctxCheck := app.BaseApp.NewContext(true, tmproto.Header{}) diff --git a/testutil/network/network.go b/testutil/network/network.go index adbc6b391b49..95202486e4ab 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -132,16 +132,31 @@ func DefaultConfig() Config { func DefaultConfigWithAppConfig(appConfig depinject.Config) (Config, error) { cfg := DefaultConfig() - var appBuilder *runtime.AppBuilder - var msgServiceRouter *baseapp.MsgServiceRouter + + var ( + appBuilder *runtime.AppBuilder + msgServiceRouter *baseapp.MsgServiceRouter + txConfig client.TxConfig + legacyAmino *codec.LegacyAmino + codec codec.Codec + interfaceRegistry codectypes.InterfaceRegistry + ) if err := depinject.Inject(appConfig, &appBuilder, &msgServiceRouter, + &txConfig, + &codec, + &legacyAmino, + &interfaceRegistry, ); err != nil { return Config{}, err } + cfg.Codec = codec + cfg.TxConfig = txConfig + cfg.LegacyAmino = legacyAmino + cfg.InterfaceRegistry = interfaceRegistry cfg.GenesisState = appBuilder.DefaultGenesis() cfg.AppConstructor = func(val Validator) servertypes.Application { app := appBuilder.Build( diff --git a/testutil/sims/address_helpers.go b/testutil/sims/address_helpers.go new file mode 100644 index 000000000000..15924f35794e --- /dev/null +++ b/testutil/sims/address_helpers.go @@ -0,0 +1,96 @@ +package sims + +import ( + "bytes" + "fmt" + "strconv" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" +) + +type GenerateAccountStrategy func(int) []sdk.AccAddress + +// AddTestAddrsIncremental constructs and returns accNum amount of accounts with an initial balance of accAmt in random order +func AddTestAddrsIncremental(bankKeeper bankkeeper.Keeper, stakingKeeper *stakingkeeper.Keeper, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { + return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateIncrementalAccounts) +} + +func addTestAddrs(bankKeeper bankkeeper.Keeper, stakingKeeper *stakingkeeper.Keeper, ctx sdk.Context, accNum int, accAmt math.Int, strategy GenerateAccountStrategy) []sdk.AccAddress { + testAddrs := strategy(accNum) + initCoins := sdk.NewCoins(sdk.NewCoin(stakingKeeper.BondDenom(ctx), accAmt)) + + for _, addr := range testAddrs { + initAccountWithCoins(bankKeeper, ctx, addr, initCoins) + } + + return testAddrs +} + +func initAccountWithCoins(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, coins sdk.Coins) { + if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, coins); err != nil { + panic(err) + } + + if err := bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, coins); err != nil { + panic(err) + } +} + +// createIncrementalAccounts is a strategy used by addTestAddrs() in order to generated addresses in ascending order. +func CreateIncrementalAccounts(accNum int) []sdk.AccAddress { + var addresses []sdk.AccAddress + var buffer bytes.Buffer + + // start at 100 so we can make up to 999 test addresses with valid test addresses + for i := 100; i < (accNum + 100); i++ { + numString := strconv.Itoa(i) + buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string + + buffer.WriteString(numString) // adding on final two digits to make addresses unique + res, _ := sdk.AccAddressFromHexUnsafe(buffer.String()) + bech := res.String() + addr, _ := TestAddr(buffer.String(), bech) + + addresses = append(addresses, addr) + buffer.Reset() + } + + return addresses +} + +// CreateRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order. +func CreateRandomAccounts(accNum int) []sdk.AccAddress { + testAddrs := make([]sdk.AccAddress, accNum) + for i := 0; i < accNum; i++ { + pk := ed25519.GenPrivKey().PubKey() + testAddrs[i] = sdk.AccAddress(pk.Address()) + } + + return testAddrs +} + +func TestAddr(addr string, bech string) (sdk.AccAddress, error) { + res, err := sdk.AccAddressFromHexUnsafe(addr) + if err != nil { + return nil, err + } + bechexpected := res.String() + if bech != bechexpected { + return nil, fmt.Errorf("bech encoding doesn't match reference") + } + + bechres, err := sdk.AccAddressFromBech32(bech) + if err != nil { + return nil, err + } + if !bytes.Equal(bechres, res) { + return nil, err + } + + return res, nil +} diff --git a/testutil/sims/app_helpers.go b/testutil/sims/app_helpers.go new file mode 100644 index 000000000000..01b1f336bc33 --- /dev/null +++ b/testutil/sims/app_helpers.go @@ -0,0 +1,184 @@ +package sims + +import ( + "context" + "encoding/json" + "fmt" + "time" + + abci "github.com/tendermint/tendermint/abci/types" + tmjson "github.com/tendermint/tendermint/libs/json" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtypes "github.com/tendermint/tendermint/types" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/depinject" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/mock" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// DefaultConsensusParams defines the default Tendermint consensus params used in +// SimApp testing. +var DefaultConsensusParams = &tmproto.ConsensusParams{ + Block: &tmproto.BlockParams{ + MaxBytes: 200000, + MaxGas: 2000000, + }, + Evidence: &tmproto.EvidenceParams{ + MaxAgeNumBlocks: 302400, + MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration + MaxBytes: 10000, + }, + Validator: &tmproto.ValidatorParams{ + PubKeyTypes: []string{ + tmtypes.ABCIPubKeyTypeEd25519, + }, + }, +} + +// Setup initializes a new runtime.App. A Nop logger is set in runtime.App. +// appConfig usually load from a `app.yaml` with `appconfig.LoadYAML`, defines the application configuration. +// extraOutputs defines the extra outputs to be assigned by the dependency injector (depinject). +func Setup(appConfig depinject.Config, extraOutputs ...interface{}) (*runtime.App, error) { + // + // create app + // + var appBuilder *runtime.AppBuilder + var msgServiceRouter *baseapp.MsgServiceRouter + var codec codec.Codec + + if err := depinject.Inject( + appConfig, + append(extraOutputs, &appBuilder, &msgServiceRouter, &codec)..., + ); err != nil { + return nil, fmt.Errorf("failed to inject dependencies: %w", err) + } + + app := appBuilder.Build(log.NewNopLogger(), dbm.NewMemDB(), nil, msgServiceRouter) + if err := app.Load(true); err != nil { + return nil, fmt.Errorf("failed to load app: %w", err) + } + + // + // create genesis and validator + // + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey(context.TODO()) + if err != nil { + return nil, fmt.Errorf("failed to get pub key: %w", err) + } + + // create validator set with single validator + validator := tmtypes.NewValidator(pubKey, 1) + valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) + + // generate genesis account + senderPrivKey := secp256k1.GenPrivKey() + acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))), + } + + genesisState, err := GenesisStateWithValSet(codec, appBuilder.DefaultGenesis(), valSet, []authtypes.GenesisAccount{acc}, balance) + if err != nil { + return nil, fmt.Errorf("failed to create genesis state: %w", err) + } + + // init chain must be called to stop deliverState from being nil + stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ") + if err != nil { + return nil, fmt.Errorf("failed to marshal default genesis state: %w", err) + } + + // init chain will set the validator set and initialize the genesis accounts + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: DefaultConsensusParams, + AppStateBytes: stateBytes, + }, + ) + + return app, nil +} + +// GenesisStateWithValSet returns a new genesis state with the validator set +func GenesisStateWithValSet(codec codec.Codec, genesisState map[string]json.RawMessage, + valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, + balances ...banktypes.Balance, +) (map[string]json.RawMessage, error) { + // set genesis accounts + authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) + genesisState[authtypes.ModuleName] = codec.MustMarshalJSON(authGenesis) + + validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) + delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) + + bondAmt := sdk.DefaultPowerReduction + + for _, val := range valSet.Validators { + pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) + if err != nil { + return nil, fmt.Errorf("failed to convert pubkey: %w", err) + } + + pkAny, err := codectypes.NewAnyWithValue(pk) + if err != nil { + return nil, fmt.Errorf("failed to create new any: %w", err) + } + + validator := stakingtypes.Validator{ + OperatorAddress: sdk.ValAddress(val.Address).String(), + ConsensusPubkey: pkAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: bondAmt, + DelegatorShares: sdk.OneDec(), + Description: stakingtypes.Description{}, + UnbondingHeight: int64(0), + UnbondingTime: time.Unix(0, 0).UTC(), + Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), + MinSelfDelegation: sdk.ZeroInt(), + } + validators = append(validators, validator) + delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) + + } + // set validators and delegations + stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) + genesisState[stakingtypes.ModuleName] = codec.MustMarshalJSON(stakingGenesis) + + totalSupply := sdk.NewCoins() + for _, b := range balances { + // add genesis acc tokens to total supply + totalSupply = totalSupply.Add(b.Coins...) + } + + for range delegations { + // add delegated tokens to total supply + totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)) + } + + // add bonded amount to bonded pool module account + balances = append(balances, banktypes.Balance{ + Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), + Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + }) + + // update total supply + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}, []banktypes.SendEnabled{}) + genesisState[banktypes.ModuleName] = codec.MustMarshalJSON(bankGenesis) + + return genesisState, nil +} diff --git a/testutil/sims/helpers.go b/testutil/sims/helpers.go deleted file mode 100644 index b74de98ddd18..000000000000 --- a/testutil/sims/helpers.go +++ /dev/null @@ -1,27 +0,0 @@ -package sims - -import ( - "time" - - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" -) - -// DefaultConsensusParams defines the default Tendermint consensus params used in -// SimApp testing. -var DefaultConsensusParams = &tmproto.ConsensusParams{ - Block: &tmproto.BlockParams{ - MaxBytes: 200000, - MaxGas: 2000000, - }, - Evidence: &tmproto.EvidenceParams{ - MaxAgeNumBlocks: 302400, - MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration - MaxBytes: 10000, - }, - Validator: &tmproto.ValidatorParams{ - PubKeyTypes: []string{ - tmtypes.ABCIPubKeyTypeEd25519, - }, - }, -} diff --git a/x/nft/client/testutil/cli_test.go b/x/nft/client/testutil/cli_test.go index 12544d34a846..df50cd7d3e55 100644 --- a/x/nft/client/testutil/cli_test.go +++ b/x/nft/client/testutil/cli_test.go @@ -1,7 +1,6 @@ package testutil import ( - _ "embed" "testing" "github.com/stretchr/testify/require" diff --git a/x/nft/keeper/grpc_query_test.go b/x/nft/keeper/grpc_query_test.go index 6f6090e5dd93..8afcf1c26e30 100644 --- a/x/nft/keeper/grpc_query_test.go +++ b/x/nft/keeper/grpc_query_test.go @@ -219,7 +219,7 @@ func (s *TestSuite) TestSupply() { Id: testID, Uri: testURI, } - err := s.app.NFTKeeper.Mint(s.ctx, n, s.addrs[0]) + err := s.nftKeeper.Mint(s.ctx, n, s.addrs[0]) require.NoError(err, "the error occurred on:%d", index) req = &nft.QuerySupplyRequest{ @@ -292,7 +292,7 @@ func (s *TestSuite) TestNFTs() { Id: testID, Uri: testURI, } - err := s.app.NFTKeeper.Mint(s.ctx, n, s.addrs[0]) + err := s.nftKeeper.Mint(s.ctx, n, s.addrs[0]) require.NoError(err, "the error occurred on:%d", index) }, "", @@ -303,7 +303,7 @@ func (s *TestSuite) TestNFTs() { { "Success,query by owner", func(index int, require *require.Assertions) { - err := s.app.NFTKeeper.SaveClass(s.ctx, nft.Class{ + err := s.nftKeeper.SaveClass(s.ctx, nft.Class{ Id: "MyKitty", }) require.NoError(err) @@ -314,7 +314,7 @@ func (s *TestSuite) TestNFTs() { ClassId: "MyKitty", Id: fmt.Sprintf("MyCat%d", i), } - err := s.app.NFTKeeper.Mint(s.ctx, n, s.addrs[2]) + err := s.nftKeeper.Mint(s.ctx, n, s.addrs[2]) require.NoError(err) nfts = append(nfts, &n) } diff --git a/x/nft/keeper/keeper_test.go b/x/nft/keeper/keeper_test.go index 9f18ab734116..61e6b74f4901 100644 --- a/x/nft/keeper/keeper_test.go +++ b/x/nft/keeper/keeper_test.go @@ -8,9 +8,14 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/simapp" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" "github.com/cosmos/cosmos-sdk/x/nft" + "github.com/cosmos/cosmos-sdk/x/nft/keeper" + "github.com/cosmos/cosmos-sdk/x/nft/testutil" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) const ( @@ -28,24 +33,38 @@ const ( type TestSuite struct { suite.Suite - app *simapp.SimApp ctx sdk.Context addrs []sdk.AccAddress queryClient nft.QueryClient + nftKeeper keeper.Keeper } func (s *TestSuite) SetupTest() { - app := simapp.Setup(s.T(), false) + var ( + interfaceRegistry codectypes.InterfaceRegistry + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + nftKeeper keeper.Keeper + ) + + app, err := simtestutil.Setup( + testutil.AppConfig, + &interfaceRegistry, + &nftKeeper, + &bankKeeper, + &stakingKeeper, + ) + s.Require().NoError(err) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) ctx = ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) - queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) - nft.RegisterQueryServer(queryHelper, app.NFTKeeper) - queryClient := nft.NewQueryClient(queryHelper) + queryHelper := baseapp.NewQueryServerTestHelper(ctx, interfaceRegistry) + nft.RegisterQueryServer(queryHelper, nftKeeper) - s.app = app s.ctx = ctx - s.queryClient = queryClient - s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000)) + s.queryClient = nft.NewQueryClient(queryHelper) + s.addrs = simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 3, sdk.NewInt(30000000)) + s.nftKeeper = nftKeeper } func TestTestSuite(t *testing.T) { @@ -61,14 +80,14 @@ func (s *TestSuite) TestSaveClass() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, except) + err := s.nftKeeper.SaveClass(s.ctx, except) s.Require().NoError(err) - actual, has := s.app.NFTKeeper.GetClass(s.ctx, testClassID) + actual, has := s.nftKeeper.GetClass(s.ctx, testClassID) s.Require().True(has) s.Require().EqualValues(except, actual) - classes := s.app.NFTKeeper.GetClasses(s.ctx) + classes := s.nftKeeper.GetClasses(s.ctx) s.Require().EqualValues([]*nft.Class{&except}, classes) } @@ -81,7 +100,7 @@ func (s *TestSuite) TestUpdateClass() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, class) + err := s.nftKeeper.SaveClass(s.ctx, class) s.Require().NoError(err) noExistClass := nft.Class{ @@ -93,7 +112,7 @@ func (s *TestSuite) TestUpdateClass() { UriHash: testClassURIHash, } - err = s.app.NFTKeeper.UpdateClass(s.ctx, noExistClass) + err = s.nftKeeper.UpdateClass(s.ctx, noExistClass) s.Require().Error(err) s.Require().Contains(err.Error(), "nft class does not exist") @@ -106,10 +125,10 @@ func (s *TestSuite) TestUpdateClass() { UriHash: testClassURIHash, } - err = s.app.NFTKeeper.UpdateClass(s.ctx, except) + err = s.nftKeeper.UpdateClass(s.ctx, except) s.Require().NoError(err) - actual, has := s.app.NFTKeeper.GetClass(s.ctx, testClassID) + actual, has := s.nftKeeper.GetClass(s.ctx, testClassID) s.Require().True(has) s.Require().EqualValues(except, actual) } @@ -123,7 +142,7 @@ func (s *TestSuite) TestMint() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, class) + err := s.nftKeeper.SaveClass(s.ctx, class) s.Require().NoError(err) expNFT := nft.NFT{ @@ -131,32 +150,32 @@ func (s *TestSuite) TestMint() { Id: testID, Uri: testURI, } - err = s.app.NFTKeeper.Mint(s.ctx, expNFT, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, expNFT, s.addrs[0]) s.Require().NoError(err) // test GetNFT - actNFT, has := s.app.NFTKeeper.GetNFT(s.ctx, testClassID, testID) + actNFT, has := s.nftKeeper.GetNFT(s.ctx, testClassID, testID) s.Require().True(has) s.Require().EqualValues(expNFT, actNFT) // test GetOwner - owner := s.app.NFTKeeper.GetOwner(s.ctx, testClassID, testID) + owner := s.nftKeeper.GetOwner(s.ctx, testClassID, testID) s.Require().True(s.addrs[0].Equals(owner)) // test GetNFTsOfClass - actNFTs := s.app.NFTKeeper.GetNFTsOfClass(s.ctx, testClassID) + actNFTs := s.nftKeeper.GetNFTsOfClass(s.ctx, testClassID) s.Require().EqualValues([]nft.NFT{expNFT}, actNFTs) // test GetNFTsOfClassByOwner - actNFTs = s.app.NFTKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) + actNFTs = s.nftKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues([]nft.NFT{expNFT}, actNFTs) // test GetBalance - balance := s.app.NFTKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) + balance := s.nftKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues(uint64(1), balance) // test GetTotalSupply - supply := s.app.NFTKeeper.GetTotalSupply(s.ctx, testClassID) + supply := s.nftKeeper.GetTotalSupply(s.ctx, testClassID) s.Require().EqualValues(uint64(1), supply) expNFT2 := nft.NFT{ @@ -164,15 +183,15 @@ func (s *TestSuite) TestMint() { Id: testID + "2", Uri: testURI + "2", } - err = s.app.NFTKeeper.Mint(s.ctx, expNFT2, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, expNFT2, s.addrs[0]) s.Require().NoError(err) // test GetNFTsOfClassByOwner - actNFTs = s.app.NFTKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) + actNFTs = s.nftKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues([]nft.NFT{expNFT, expNFT2}, actNFTs) // test GetBalance - balance = s.app.NFTKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) + balance = s.nftKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues(uint64(2), balance) } @@ -185,7 +204,7 @@ func (s *TestSuite) TestBurn() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, except) + err := s.nftKeeper.SaveClass(s.ctx, except) s.Require().NoError(err) expNFT := nft.NFT{ @@ -193,34 +212,34 @@ func (s *TestSuite) TestBurn() { Id: testID, Uri: testURI, } - err = s.app.NFTKeeper.Mint(s.ctx, expNFT, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, expNFT, s.addrs[0]) s.Require().NoError(err) - err = s.app.NFTKeeper.Burn(s.ctx, testClassID, testID) + err = s.nftKeeper.Burn(s.ctx, testClassID, testID) s.Require().NoError(err) // test GetNFT - _, has := s.app.NFTKeeper.GetNFT(s.ctx, testClassID, testID) + _, has := s.nftKeeper.GetNFT(s.ctx, testClassID, testID) s.Require().False(has) // test GetOwner - owner := s.app.NFTKeeper.GetOwner(s.ctx, testClassID, testID) + owner := s.nftKeeper.GetOwner(s.ctx, testClassID, testID) s.Require().Nil(owner) // test GetNFTsOfClass - actNFTs := s.app.NFTKeeper.GetNFTsOfClass(s.ctx, testClassID) + actNFTs := s.nftKeeper.GetNFTsOfClass(s.ctx, testClassID) s.Require().Empty(actNFTs) // test GetNFTsOfClassByOwner - actNFTs = s.app.NFTKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) + actNFTs = s.nftKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[0]) s.Require().Empty(actNFTs) // test GetBalance - balance := s.app.NFTKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) + balance := s.nftKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues(uint64(0), balance) // test GetTotalSupply - supply := s.app.NFTKeeper.GetTotalSupply(s.ctx, testClassID) + supply := s.nftKeeper.GetTotalSupply(s.ctx, testClassID) s.Require().EqualValues(uint64(0), supply) } @@ -233,7 +252,7 @@ func (s *TestSuite) TestUpdate() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, class) + err := s.nftKeeper.SaveClass(s.ctx, class) s.Require().NoError(err) myNFT := nft.NFT{ @@ -241,7 +260,7 @@ func (s *TestSuite) TestUpdate() { Id: testID, Uri: testURI, } - err = s.app.NFTKeeper.Mint(s.ctx, myNFT, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, myNFT, s.addrs[0]) s.Require().NoError(err) expNFT := nft.NFT{ @@ -250,11 +269,11 @@ func (s *TestSuite) TestUpdate() { Uri: "updated", } - err = s.app.NFTKeeper.Update(s.ctx, expNFT) + err = s.nftKeeper.Update(s.ctx, expNFT) s.Require().NoError(err) // test GetNFT - actNFT, has := s.app.NFTKeeper.GetNFT(s.ctx, testClassID, testID) + actNFT, has := s.nftKeeper.GetNFT(s.ctx, testClassID, testID) s.Require().True(has) s.Require().EqualValues(expNFT, actNFT) } @@ -268,7 +287,7 @@ func (s *TestSuite) TestTransfer() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, class) + err := s.nftKeeper.SaveClass(s.ctx, class) s.Require().NoError(err) expNFT := nft.NFT{ @@ -276,25 +295,25 @@ func (s *TestSuite) TestTransfer() { Id: testID, Uri: testURI, } - err = s.app.NFTKeeper.Mint(s.ctx, expNFT, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, expNFT, s.addrs[0]) s.Require().NoError(err) // valid owner - err = s.app.NFTKeeper.Transfer(s.ctx, testClassID, testID, s.addrs[1]) + err = s.nftKeeper.Transfer(s.ctx, testClassID, testID, s.addrs[1]) s.Require().NoError(err) // test GetOwner - owner := s.app.NFTKeeper.GetOwner(s.ctx, testClassID, testID) + owner := s.nftKeeper.GetOwner(s.ctx, testClassID, testID) s.Require().Equal(s.addrs[1], owner) - balanceAddr0 := s.app.NFTKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) + balanceAddr0 := s.nftKeeper.GetBalance(s.ctx, testClassID, s.addrs[0]) s.Require().EqualValues(uint64(0), balanceAddr0) - balanceAddr1 := s.app.NFTKeeper.GetBalance(s.ctx, testClassID, s.addrs[1]) + balanceAddr1 := s.nftKeeper.GetBalance(s.ctx, testClassID, s.addrs[1]) s.Require().EqualValues(uint64(1), balanceAddr1) // test GetNFTsOfClassByOwner - actNFTs := s.app.NFTKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[1]) + actNFTs := s.nftKeeper.GetNFTsOfClassByOwner(s.ctx, testClassID, s.addrs[1]) s.Require().EqualValues([]nft.NFT{expNFT}, actNFTs) } @@ -307,7 +326,7 @@ func (s *TestSuite) TestExportGenesis() { Uri: testClassURI, UriHash: testClassURIHash, } - err := s.app.NFTKeeper.SaveClass(s.ctx, class) + err := s.nftKeeper.SaveClass(s.ctx, class) s.Require().NoError(err) expNFT := nft.NFT{ @@ -315,7 +334,7 @@ func (s *TestSuite) TestExportGenesis() { Id: testID, Uri: testURI, } - err = s.app.NFTKeeper.Mint(s.ctx, expNFT, s.addrs[0]) + err = s.nftKeeper.Mint(s.ctx, expNFT, s.addrs[0]) s.Require().NoError(err) expGenesis := &nft.GenesisState{ @@ -325,7 +344,7 @@ func (s *TestSuite) TestExportGenesis() { Nfts: []*nft.NFT{&expNFT}, }}, } - genesis := s.app.NFTKeeper.ExportGenesis(s.ctx) + genesis := s.nftKeeper.ExportGenesis(s.ctx) s.Require().Equal(expGenesis, genesis) } @@ -350,14 +369,14 @@ func (s *TestSuite) TestInitGenesis() { Nfts: []*nft.NFT{&expNFT}, }}, } - s.app.NFTKeeper.InitGenesis(s.ctx, expGenesis) + s.nftKeeper.InitGenesis(s.ctx, expGenesis) - actual, has := s.app.NFTKeeper.GetClass(s.ctx, testClassID) + actual, has := s.nftKeeper.GetClass(s.ctx, testClassID) s.Require().True(has) s.Require().EqualValues(expClass, actual) // test GetNFT - actNFT, has := s.app.NFTKeeper.GetNFT(s.ctx, testClassID, testID) + actNFT, has := s.nftKeeper.GetNFT(s.ctx, testClassID, testID) s.Require().True(has) s.Require().EqualValues(expNFT, actNFT) } diff --git a/x/nft/module/module.go b/x/nft/module/module.go index 176497a7e4f5..966e23c1d764 100644 --- a/x/nft/module/module.go +++ b/x/nft/module/module.go @@ -20,7 +20,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" modulev1 "cosmossdk.io/api/cosmos/nft/module/v1" "github.com/cosmos/cosmos-sdk/x/nft" @@ -218,17 +217,16 @@ type nftInputs struct { Key *store.KVStoreKey Cdc codec.Codec - Subspace paramstypes.Subspace Registry cdctypes.InterfaceRegistry - AccountKeeper nft.AccountKeeper `key:"cosmos.auth.v1.AccountKeeper"` - BankKeeper nft.BankKeeper `key:"cosmos.bank.v1.Keeper"` + AccountKeeper nft.AccountKeeper + BankKeeper nft.BankKeeper } type nftOutputs struct { depinject.Out - NFTKeeper keeper.Keeper `key:"cosmos.nft.v1.Keeper"` + NFTKeeper keeper.Keeper Module runtime.AppModuleWrapper } diff --git a/x/nft/simulation/decoder_test.go b/x/nft/simulation/decoder_test.go index 108e424b9abb..ea8c8921625f 100644 --- a/x/nft/simulation/decoder_test.go +++ b/x/nft/simulation/decoder_test.go @@ -6,13 +6,15 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/depinject" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/nft" "github.com/cosmos/cosmos-sdk/x/nft/keeper" "github.com/cosmos/cosmos-sdk/x/nft/simulation" + "github.com/cosmos/cosmos-sdk/x/nft/testutil" ) var ( @@ -21,7 +23,8 @@ var ( ) func TestDecodeStore(t *testing.T) { - cdc := simapp.MakeTestEncodingConfig().Codec + var cdc codec.Codec + depinject.Inject(testutil.AppConfig, &cdc) dec := simulation.NewDecodeStore(cdc) class := nft.Class{ diff --git a/x/nft/simulation/genesis_test.go b/x/nft/simulation/genesis_test.go index 3586229497a0..01a5c00de067 100644 --- a/x/nft/simulation/genesis_test.go +++ b/x/nft/simulation/genesis_test.go @@ -8,22 +8,25 @@ import ( "github.com/stretchr/testify/require" sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/depinject" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/nft" "github.com/cosmos/cosmos-sdk/x/nft/simulation" + "github.com/cosmos/cosmos-sdk/x/nft/testutil" ) func TestRandomizedGenState(t *testing.T) { - app := simapp.Setup(t, false) + var cdc codec.Codec + depinject.Inject(testutil.AppConfig, &cdc) s := rand.NewSource(1) r := rand.New(s) simState := module.SimulationState{ AppParams: make(simtypes.AppParams), - Cdc: app.AppCodec(), + Cdc: cdc, Rand: r, NumBonded: 3, Accounts: simtypes.RandomAccounts(r, 3), diff --git a/x/nft/simulation/operations.go b/x/nft/simulation/operations.go index b45a56ca1f98..904745c54fb0 100644 --- a/x/nft/simulation/operations.go +++ b/x/nft/simulation/operations.go @@ -7,9 +7,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/simapp/helpers" - simappparams "github.com/cosmos/cosmos-sdk/simapp/params" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/nft" "github.com/cosmos/cosmos-sdk/x/nft/keeper" @@ -96,7 +96,7 @@ func SimulateMsgSend( Receiver: receiver.Address.String(), } - txCfg := simappparams.MakeTestEncodingConfig().TxConfig + txCfg := tx.NewTxConfig(cdc, tx.DefaultSignModes) tx, err := helpers.GenSignedMockTx( txCfg, []sdk.Msg{msg}, diff --git a/x/nft/simulation/operations_test.go b/x/nft/simulation/operations_test.go index 0a500f5a971c..943f6dfac8fc 100644 --- a/x/nft/simulation/operations_test.go +++ b/x/nft/simulation/operations_test.go @@ -11,35 +11,59 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/bank/testutil" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" "github.com/cosmos/cosmos-sdk/x/nft" + nftkeeper "github.com/cosmos/cosmos-sdk/x/nft/keeper" "github.com/cosmos/cosmos-sdk/x/nft/simulation" + "github.com/cosmos/cosmos-sdk/x/nft/testutil" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" ) type SimTestSuite struct { suite.Suite ctx sdk.Context - app *simapp.SimApp + + app *runtime.App + codec codec.Codec + interfaceRegistry codectypes.InterfaceRegistry + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + nftKeeper nftkeeper.Keeper } func (suite *SimTestSuite) SetupTest() { - checkTx := false - app := simapp.Setup(suite.T(), checkTx) + app, err := simtestutil.Setup( + testutil.AppConfig, + &suite.codec, + &suite.interfaceRegistry, + &suite.accountKeeper, + &suite.bankKeeper, + &suite.stakingKeeper, + &suite.nftKeeper, + ) + suite.Require().NoError(err) + suite.app = app - suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) + suite.ctx = app.BaseApp.NewContext(false, tmproto.Header{}) } func (suite *SimTestSuite) TestWeightedOperations() { weightedOps := simulation.WeightedOperations( - suite.app.InterfaceRegistry(), + suite.interfaceRegistry, make(simtypes.AppParams), - suite.app.AppCodec(), - suite.app.AccountKeeper, - suite.app.BankKeeper, suite.app.NFTKeeper, + suite.codec, + suite.accountKeeper, + suite.bankKeeper, + suite.nftKeeper, ) // setup 3 accounts @@ -61,7 +85,7 @@ func (suite *SimTestSuite) TestWeightedOperations() { // by WeightedOperations. if the ordering in WeightedOperations changes some tests // will fail suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") - suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") + suite.Require().Contains(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") } } @@ -69,14 +93,14 @@ func (suite *SimTestSuite) TestWeightedOperations() { func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { accounts := simtypes.RandomAccounts(r, n) - initAmt := suite.app.StakingKeeper.TokensFromConsensusPower(suite.ctx, 200000) + initAmt := suite.stakingKeeper.TokensFromConsensusPower(suite.ctx, 200000) initCoins := sdk.NewCoins(sdk.NewCoin("stake", initAmt)) // add coins to the accounts for _, account := range accounts { - acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) - suite.app.AccountKeeper.SetAccount(suite.ctx, acc) - suite.Require().NoError(testutil.FundAccount(suite.app.BankKeeper, suite.ctx, account.Address, initCoins)) + acc := suite.accountKeeper.NewAccountWithAddress(suite.ctx, account.Address) + suite.accountKeeper.SetAccount(suite.ctx, acc) + suite.Require().NoError(banktestutil.FundAccount(suite.bankKeeper, suite.ctx, account.Address, initCoins)) } return accounts @@ -98,13 +122,13 @@ func (suite *SimTestSuite) TestSimulateMsgSend() { }) // execute operation - registry := suite.app.InterfaceRegistry() - op := simulation.SimulateMsgSend(codec.NewProtoCodec(registry), suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.NFTKeeper) + registry := suite.interfaceRegistry + op := simulation.SimulateMsgSend(codec.NewProtoCodec(registry), suite.accountKeeper, suite.bankKeeper, suite.nftKeeper) operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") suite.Require().NoError(err) var msg nft.MsgSend - suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.codec.UnmarshalJSON(operationMsg.Msg, &msg) suite.Require().True(operationMsg.OK) suite.Require().Len(futureOperations, 0) } diff --git a/x/nft/spec/01_concepts.md b/x/nft/spec/01_concepts.md index ae4bbd99f7c9..b69b16710ff8 100644 --- a/x/nft/spec/01_concepts.md +++ b/x/nft/spec/01_concepts.md @@ -11,3 +11,9 @@ order: 1 ## NFT The full name of NFT is Non-Fungible Tokens. Because of the irreplaceable nature of NFT, it means that it can be used to represent unique things. The nft implemented by this module is fully compatible with Ethereum ERC721 standard. + +## App Wiring + +The minimal app-wiring configuration for this `x/nft` is as follows: + ++++ https://github.com/cosmos/cosmos-sdk/blob/main/x/nft/testutil/app.yaml diff --git a/x/nft/testutil/app.yaml b/x/nft/testutil/app.yaml index ff5f3ffc9b23..275b26826684 100644 --- a/x/nft/testutil/app.yaml +++ b/x/nft/testutil/app.yaml @@ -3,11 +3,11 @@ modules: config: "@type": cosmos.app.runtime.v1alpha1.Module - app_name: NftApp + app_name: NFTApp - begin_blockers: [staking, auth, bank, genutil, nft, params] - end_blockers: [staking, auth, bank, genutil, nft, params] - init_genesis: [auth, bank, staking, genutil, nft, params] + begin_blockers: [mint, staking, auth, bank, mint, genutil, nft, params] + end_blockers: [mint, staking, auth, bank, mint, genutil, nft, params] + init_genesis: [auth, bank, mint, staking, mint, genutil, nft, params] - name: auth config: @@ -15,6 +15,8 @@ modules: bech32_prefix: cosmos module_account_permissions: - account: fee_collector + - account: mint + permissions: [minter] - account: bonded_tokens_pool permissions: [burner, staking] - account: not_bonded_tokens_pool @@ -33,10 +35,6 @@ modules: config: "@type": cosmos.tx.module.v1.Module - - name: nft - config: - "@type": cosmos.nft.module.v1.Module - - name: staking config: "@type": cosmos.staking.module.v1.Module @@ -44,3 +42,11 @@ modules: - name: genutil config: "@type": cosmos.genutil.module.v1.Module + + - name: mint + config: + "@type": cosmos.mint.module.v1.Module + + - name: nft + config: + "@type": cosmos.nft.module.v1.Module diff --git a/x/nft/testutil/app_config.go b/x/nft/testutil/app_config.go index 1f01697aa019..69487c5fac35 100644 --- a/x/nft/testutil/app_config.go +++ b/x/nft/testutil/app_config.go @@ -4,6 +4,14 @@ import ( _ "embed" "cosmossdk.io/core/appconfig" + _ "github.com/cosmos/cosmos-sdk/x/auth" + _ "github.com/cosmos/cosmos-sdk/x/auth/tx/module" + _ "github.com/cosmos/cosmos-sdk/x/bank" + _ "github.com/cosmos/cosmos-sdk/x/genutil" + _ "github.com/cosmos/cosmos-sdk/x/mint" + _ "github.com/cosmos/cosmos-sdk/x/nft/module" + _ "github.com/cosmos/cosmos-sdk/x/params" + _ "github.com/cosmos/cosmos-sdk/x/staking" ) //go:embed app.yaml