diff --git a/.github/workflows/chain_simulation_tests.yml b/.github/workflows/chain_simulation_tests.yml index 6d7db0f9d..edbf3cab1 100644 --- a/.github/workflows/chain_simulation_tests.yml +++ b/.github/workflows/chain_simulation_tests.yml @@ -2,12 +2,15 @@ name: "Simulation tests on EmpowerChain" on: workflow_dispatch: + schedule: + - cron: "0 */2 * * *" jobs: sim-tests: name: Run EmpowerChain simulation tests runs-on: ubuntu-22.04 strategy: + fail-fast: false matrix: test: [ diff --git a/.github/workflows/chain_test.yml b/.github/workflows/chain_test.yml index 3c01c1cde..c08897d71 100644 --- a/.github/workflows/chain_test.yml +++ b/.github/workflows/chain_test.yml @@ -31,5 +31,28 @@ jobs: flags: chain fail_ci_if_error: true + smoke-test: + name: Smoke tests EmpowerChain + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - uses: earthly/actions-setup@v1 + with: + version: v0.6.30 + - run: earthly --ci +smoketest working-directory: ./chain + + non-determinism-test: + name: Simulation non-determinism tests EmpowerChain + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - uses: earthly/actions-setup@v1 + with: + version: v0.6.30 + + - run: earthly --ci +test-sim-nondeterminism + working-directory: ./chain \ No newline at end of file diff --git a/chain/CODING_GUIDELINES.md b/chain/CODING_GUIDELINES.md index 85b54ad9d..2b76df8aa 100644 --- a/chain/CODING_GUIDELINES.md +++ b/chain/CODING_GUIDELINES.md @@ -106,19 +106,19 @@ If you are not sure what a good way of doing something in particular, there are 3. Implement/Update `Validate()` on any non-rpc messages (i.e. data structures to be persisted in the keeper and in genesis) 4. If you created any new rpc messages: - Implement the `sdk.Msg` interface in `msgs.go` (`_ sdk.Msg = &MsgName{}`) + - Update `WeightedOperations` in simulation/operations.go with the new operation - Don't forget to create tests for `ValidateBasic`! 5. Implement `MsgServer`/`Querier` and `Keeper` methods - Don't forget events - Don't forget integration tests - If you create public Keeper methods, they need to be tested as well -6. Update genesis if necessary (in genesis and keeper/genesis) -7. Update the client/cli if necessary -8. Create e2e tests in `scripts/test/` - - Remember to `$ make install` after every change you make so the binary under test is the correct one. - - Hot tip: stop the test at some point before the serve is killed with `exit 0` and run just the script (e.g. `$ ./scripts/test/smoke_plastic_credit.sh`). - - This way the server is still running, and you can manually run your CLI commands in the terminal. - - To get access to the environment variables such as `$CHAIN_ID` and `$CHAIN_DIR` you can use the env script like this: `$ source ./scripts/serve_env.sh`. -9. Format and lint your code before committing: `$ make format` and `$ make lint` +6. If you created a new type to be stored (i.e. you added a new store key in keys.go) + - Update `NewDecodeStore` in simulation/decoder.go +7. Update genesis if necessary (in genesis and keeper/genesis) + - Update `RandomizedGenState` in simulation/genesis.go if necessary +8. Update the client/cli if necessary +9. Create e2e tests in `tests/e2e` +10. Format and lint your code before committing: `$ make format` and `$ make lint` ## Native modules vs smart contracts Short version: core stable functionality/protocol implemented as native Cosmos SDK modules, extra functionality/nice-to-have stuff that can change often as smart contracts. diff --git a/chain/Earthfile b/chain/Earthfile index 796019286..be9c8adb8 100644 --- a/chain/Earthfile +++ b/chain/Earthfile @@ -48,6 +48,26 @@ test-with-coverage: RUN make test-with-coverage SAVE ARTIFACT coverage.out AS LOCAL coverage.out +test-sim-import-export: + FROM +build + RUN make test-sim-import-export + +test-sim-after-import: + FROM +build + RUN make test-sim-after-import + +test-sim-multi-seed-short: + FROM +build + RUN make test-sim-multi-seed-short + +test-sim-multi-seed-long: + FROM +build + RUN make test-sim-multi-seed-long + +test-sim-nondeterminism: + FROM +build + RUN make test-sim-nondeterminism + smoketest: FROM +build RUN make smoketest diff --git a/chain/Makefile b/chain/Makefile index d5368d63e..c13d69275 100644 --- a/chain/Makefile +++ b/chain/Makefile @@ -147,6 +147,52 @@ smoketest: install smoketest-ibc: install ./scripts/test/smoke_ibc.sh +############################################################################### +### Simulations ### +############################################################################### + +SIMAPP = github.com/EmpowerPlastic/empowerchain/app/simulation +SIM_TEST_DIR = ./app/simulation +TOOLS_DESTDIR ?= $(GOPATH)/bin +RUNSIM = $(TOOLS_DESTDIR)/runsim +default_seeds := 1,2,4,7,32,123,124,582,1893,2989,3012,4728,37827,981928,87821, \ + 891823782,989182,89182391,11,22,44,77,99,2020,3232,123123,124124,582582,18931893, \ + 29892989,30123012,47284728,7601778,8090485,977367484,491163361,424254581,673398983 + +JOBS ?= 4 +SEED ?= 1 +SEEDS ?= $(subst $(whitespace),$(empty),$(default_seeds)) +PERIOD ?= 5 +NUM_BLOCKS ?= 100 +BLOCK_SIZE ?= 200 + +# Install the runsim binary +runsim: $(RUNSIM) +$(RUNSIM): + @echo "Installing runsim..." + @go install github.com/cosmos/tools/cmd/runsim@v1.0.0 + +test-sim-import-export: runsim + @echo "Running application import/export simulation. This may take several minutes..." + @runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppImportExport + +test-sim-after-import: runsim + @echo "Running application simulation-after-import. This may take several minutes..." + @runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 5 TestAppSimulationAfterImport + +test-sim-multi-seed-short: runsim + @echo "Running short multi-seed application simulation. This may take awhile!" + @runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 50 10 TestFullAppSimulation + +test-sim-multi-seed-long: runsim + @echo "Running long multi-seed application simulation. This may take awhile!" + @runsim -Jobs=4 -SimAppPkg=$(SIMAPP) -ExitOnFail 500 50 TestFullAppSimulation + +test-sim-nondeterminism: + @echo "Running non-determinism test..." + go test $(SIM_TEST_DIR) -mod=readonly -run TestAppStateDeterminism -Enabled=true \ + -NumBlocks=100 -BlockSize=200 -Commit=true -Period=0 -v -timeout 24h + ############################################################################### ### Proto ### ############################################################################### diff --git a/chain/app/app.go b/chain/app/app.go index dbf7ed3a7..9438cc948 100644 --- a/chain/app/app.go +++ b/chain/app/app.go @@ -263,7 +263,7 @@ type EmpowerApp struct { ScopedTransferKeeper capabilitykeeper.ScopedKeeper ScopedIBCFeeKeeper capabilitykeeper.ScopedKeeper - moduleManager *module.Manager + ModuleManager *module.Manager configurator module.Configurator simulationManager *module.SimulationManager @@ -514,7 +514,7 @@ func New( // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. - app.moduleManager = module.NewManager( + app.ModuleManager = module.NewManager( genutil.NewAppModule( app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, encodingConfig.TxConfig, @@ -538,7 +538,7 @@ func New( consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), // Custom modules proofofexistencemodule.NewAppModule(app.ProofofexistenceKeeper), - plasticcreditmodule.NewAppModule(appCodec, app.PlasticcreditKeeper), + plasticcreditmodule.NewAppModule(appCodec, app.PlasticcreditKeeper, app.AccountKeeper, app.BankKeeper), accesscontrolmodule.NewAppModule(app.AccessControlKeeper), // IBC modules ibc.NewAppModule(app.IBCKeeper), @@ -552,7 +552,7 @@ func New( // CanWithdrawInvariant invariant. // NOTE: staking module is required if HistoricalEntries param > 0 // NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC) - app.moduleManager.SetOrderBeginBlockers( + app.ModuleManager.SetOrderBeginBlockers( upgradetypes.ModuleName, capabilitytypes.ModuleName, minttypes.ModuleName, @@ -582,7 +582,7 @@ func New( ibcfeetypes.ModuleName, ) - app.moduleManager.SetOrderEndBlockers( + app.ModuleManager.SetOrderEndBlockers( crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName, @@ -618,7 +618,7 @@ func New( // NOTE: Capability module must occur first so that it can initialize any capabilities // so that other modules that want to create or claim capabilities afterwards in InitChain // can do so safely. - app.moduleManager.SetOrderInitGenesis( + app.ModuleManager.SetOrderInitGenesis( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, @@ -648,16 +648,16 @@ func New( ibcfeetypes.ModuleName, ) - app.moduleManager.RegisterInvariants(app.CrisisKeeper) + app.ModuleManager.RegisterInvariants(app.CrisisKeeper) app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()) - app.moduleManager.RegisterServices(app.configurator) + app.ModuleManager.RegisterServices(app.configurator) // RegisterUpgradeHandlers is used for registering any on-chain upgrades. // Make sure it's called after `app.ModuleManager` and `app.configurator` are set. app.setupUpgradeStoreLoaders() app.setupUpgradeHandlers() - autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.moduleManager.Modules)) + autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules)) reflectionSvc, err := runtimeservices.NewReflectionService() if err != nil { panic(err) @@ -671,7 +671,7 @@ func New( overrideModules := map[string]module.AppModuleSimulation{ authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)), } - app.simulationManager = module.NewSimulationManagerFromAppModules(app.moduleManager.Modules, overrideModules) + app.simulationManager = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules) app.simulationManager.RegisterStoreDecoders() // initialize stores @@ -738,12 +738,12 @@ func (app *EmpowerApp) Name() string { return app.BaseApp.Name() } // BeginBlocker application updates every begin block func (app *EmpowerApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { - return app.moduleManager.BeginBlock(ctx, req) + return app.ModuleManager.BeginBlock(ctx, req) } // EndBlocker application updates every end block func (app *EmpowerApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - return app.moduleManager.EndBlock(ctx, req) + return app.ModuleManager.EndBlock(ctx, req) } // InitChainer application update at chain initialization @@ -752,8 +752,8 @@ func (app *EmpowerApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) a if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil { panic(err) } - app.UpgradeKeeper.SetModuleVersionMap(ctx, app.moduleManager.GetVersionMap()) - return app.moduleManager.InitGenesis(ctx, app.appCodec, genesisState) + app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap()) + return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState) } // LoadHeight loads a particular height @@ -867,7 +867,7 @@ func (app *EmpowerApp) setupUpgradeHandlers() { for _, u := range Upgrades { app.UpgradeKeeper.SetUpgradeHandler( u.UpgradeName, - u.CreateUpgradeHandler(app.moduleManager, app.configurator), + u.CreateUpgradeHandler(app.ModuleManager, app.configurator), ) } } diff --git a/chain/app/export.go b/chain/app/export.go index b4aa23c77..26acacbf7 100644 --- a/chain/app/export.go +++ b/chain/app/export.go @@ -27,7 +27,7 @@ func (app *EmpowerApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllow app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs) } - genState := app.moduleManager.ExportGenesisForModules(ctx, app.appCodec, modulesToExport) + genState := app.ModuleManager.ExportGenesisForModules(ctx, app.appCodec, modulesToExport) appState, err := json.MarshalIndent(genState, "", " ") if err != nil { return servertypes.ExportedApp{}, err @@ -74,20 +74,21 @@ func (app *EmpowerApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr // withdraw all validator commission app.StakingKeeper.IterateValidators(ctx, func(_ int64, val stakingtypes.ValidatorI) (stop bool) { - _, err := app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) - if err != nil { - panic(err) - } + _, _ = app.DistrKeeper.WithdrawValidatorCommission(ctx, val.GetOperator()) return false }) // withdraw all delegator rewards dels := app.StakingKeeper.GetAllDelegations(ctx) for _, delegation := range dels { - _, err := app.DistrKeeper.WithdrawDelegationRewards(ctx, delegation.GetDelegatorAddr(), delegation.GetValidatorAddr()) + valAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) if err != nil { panic(err) } + + delAddr := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) + + _, _ = app.DistrKeeper.WithdrawDelegationRewards(ctx, delAddr, valAddr) } // clear validator slash events @@ -163,7 +164,7 @@ func (app *EmpowerApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr counter := int16(0) for ; iter.Valid(); iter.Next() { - addr := sdk.ValAddress(iter.Key()[1:]) + addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key())) validator, found := app.StakingKeeper.GetValidator(ctx, addr) if !found { panic("expected validator, not found") @@ -178,10 +179,13 @@ func (app *EmpowerApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddr counter++ } - iter.Close() + if err := iter.Close(); err != nil { + app.Logger().Error("error while closing the key-value store reverse prefix iterator: ", err) + return + } if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil { - panic(err) + log.Fatal(err) } /* Handle slashing state. */ diff --git a/chain/app/simulation/app_after_import_test.go b/chain/app/simulation/app_after_import_test.go new file mode 100644 index 000000000..6b8bc0b55 --- /dev/null +++ b/chain/app/simulation/app_after_import_test.go @@ -0,0 +1,99 @@ +package simulation + +import ( + "fmt" + "os" + "testing" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" +) + +func TestAppSimulationAfterImport(t *testing.T) { + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + + db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "empower-chain", "empower-chain-sim", simcli.FlagVerboseValue, simcli.FlagEnabledValue) + if skip { + t.Skip("skipping application simulation after import") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + + empowerApp := app.New(logger, db, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "empowerchain", empowerApp.Name()) + + // Run randomized simulation + stopEarly, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + empowerApp.BaseApp, + AppStateFn(empowerApp.AppCodec(), empowerApp.SimulationManager()), + simtypes.RandomAccounts, + simtestutil.SimulationOperations(empowerApp, empowerApp.AppCodec(), config), + app.BlockedAddresses(), + config, + empowerApp.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(empowerApp, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } + + if stopEarly { + fmt.Println("can't export or import a zero-validator genesis, exiting test...") + return + } + + fmt.Printf("exporting genesis...\n") + + exported, err := empowerApp.ExportAppStateAndValidators(true, []string{}, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + newDB, newDir, _, _, err := simtestutil.SetupSimulation(config, "empower-chain-2", "empower-chain-sim-2", simcli.FlagVerboseValue, simcli.FlagEnabledValue) + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, newDB.Close()) + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := app.New(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "empowerchain", newApp.Name()) + + newApp.InitChain(abci.RequestInitChain{ + AppStateBytes: exported.AppState, + }) + + _, _, err = simulation.SimulateFromSeed( + t, + os.Stdout, + newApp.BaseApp, + AppStateFn(newApp.AppCodec(), newApp.SimulationManager()), + simtypes.RandomAccounts, + simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), + app.BlockedAddresses(), + config, + newApp.AppCodec(), + ) + require.NoError(t, err) +} diff --git a/chain/app/simulation/app_import_export_test.go b/chain/app/simulation/app_import_export_test.go new file mode 100644 index 000000000..1445a838c --- /dev/null +++ b/chain/app/simulation/app_import_export_test.go @@ -0,0 +1,156 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "os" + "runtime/debug" + "strings" + "testing" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" + "github.com/EmpowerPlastic/empowerchain/x/accesscontrol" + plasticcreditmoduletypes "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + proofofexistencemoduletypes "github.com/EmpowerPlastic/empowerchain/x/proofofexistence" +) + +func TestAppImportExport(t *testing.T) { + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + + db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "empower-chain", "empower-chain-sim", simcli.FlagVerboseValue, simcli.FlagEnabledValue) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + empowerApp := app.New(logger, db, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "empowerchain", empowerApp.Name()) + + // Run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + empowerApp.BaseApp, + AppStateFn(empowerApp.AppCodec(), empowerApp.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(empowerApp, empowerApp.AppCodec(), config), + app.BlockedAddresses(), + config, + empowerApp.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(empowerApp, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } + + fmt.Printf("exporting genesis...\n") + + exported, err := empowerApp.ExportAppStateAndValidators(false, []string{}, []string{}) + require.NoError(t, err) + + fmt.Printf("importing genesis...\n") + + newDB, newDir, _, _, err := simtestutil.SetupSimulation(config, "empower-chain-2", "empower-chain-sim-2", simcli.FlagVerboseValue, simcli.FlagEnabledValue) + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, newDB.Close()) + require.NoError(t, os.RemoveAll(newDir)) + }() + + newApp := app.New(log.NewNopLogger(), newDB, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "empowerchain", newApp.Name()) + + var genesisState app.GenesisState + err = json.Unmarshal(exported.AppState, &genesisState) + require.NoError(t, err) + + defer func() { + if r := recover(); r != nil { + err := fmt.Sprintf("%v", r) + if !strings.Contains(err, "validator set is empty after InitGenesis") { + panic(r) + } + logger.Info("Skipping simulation as all validators have been unbonded") + logger.Info("err", err, "stacktrace", string(debug.Stack())) + } + }() + + ctxA := empowerApp.NewContext(true, tmproto.Header{Height: empowerApp.LastBlockHeight()}) + ctxB := newApp.NewContext(true, tmproto.Header{Height: empowerApp.LastBlockHeight()}) + newApp.ModuleManager.InitGenesis(ctxB, empowerApp.AppCodec(), genesisState) + newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) + + fmt.Printf("comparing stores...\n") + + storeKeysPrefixes := []StoreKeysPrefixes{ + {empowerApp.GetStoreKey(authtypes.StoreKey), newApp.GetStoreKey(authtypes.StoreKey), [][]byte{}}, + { + empowerApp.GetStoreKey(stakingtypes.StoreKey), newApp.GetStoreKey(stakingtypes.StoreKey), + [][]byte{ + stakingtypes.UnbondingQueueKey, stakingtypes.RedelegationQueueKey, stakingtypes.ValidatorQueueKey, + stakingtypes.HistoricalInfoKey, stakingtypes.UnbondingIDKey, stakingtypes.UnbondingIndexKey, stakingtypes.UnbondingTypeKey, stakingtypes.ValidatorUpdatesKey, + }, + }, // ordering may change but it doesn't matter + {empowerApp.GetStoreKey(slashingtypes.StoreKey), newApp.GetStoreKey(slashingtypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(minttypes.StoreKey), newApp.GetStoreKey(minttypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(distrtypes.StoreKey), newApp.GetStoreKey(distrtypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(banktypes.StoreKey), newApp.GetStoreKey(banktypes.StoreKey), [][]byte{banktypes.BalancesPrefix}}, + {empowerApp.GetStoreKey(paramstypes.StoreKey), newApp.GetStoreKey(paramstypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(govtypes.StoreKey), newApp.GetStoreKey(govtypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(evidencetypes.StoreKey), newApp.GetStoreKey(evidencetypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(capabilitytypes.StoreKey), newApp.GetStoreKey(capabilitytypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(ibcexported.StoreKey), newApp.GetStoreKey(ibcexported.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(ibctransfertypes.StoreKey), newApp.GetStoreKey(ibctransfertypes.StoreKey), [][]byte{}}, + // TODO: pending some feedback from SDK team, this is also not in simapp, but I don't know why + // {empowerApp.GetStoreKey(feegrant.StoreKey), newApp.GetStoreKey(feegrant.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(authzkeeper.StoreKey), newApp.GetStoreKey(authzkeeper.StoreKey), [][]byte{authzkeeper.GrantKey, authzkeeper.GrantQueuePrefix}}, + {empowerApp.GetStoreKey(proofofexistencemoduletypes.StoreKey), newApp.GetStoreKey(proofofexistencemoduletypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(plasticcreditmoduletypes.StoreKey), newApp.GetStoreKey(plasticcreditmoduletypes.StoreKey), [][]byte{}}, + {empowerApp.GetStoreKey(accesscontrol.StoreKey), newApp.GetStoreKey(accesscontrol.StoreKey), [][]byte{}}, + } + + for _, skp := range storeKeysPrefixes { + storeA := ctxA.KVStore(skp.A) + storeB := ctxB.KVStore(skp.B) + + failedKVAs, failedKVBs := sdk.DiffKVStores(storeA, storeB, skp.Prefixes) + require.Equal(t, len(failedKVAs), len(failedKVBs), "unequal sets of key-values to compare") + + fmt.Printf("compared %d different key/value pairs between %s and %s\n", len(failedKVAs), skp.A, skp.B) + require.Equal(t, 0, len(failedKVAs), simtestutil.GetSimulationLog(skp.A.Name(), empowerApp.SimulationManager().StoreDecoders, failedKVAs, failedKVBs)) + } +} diff --git a/chain/app/simulation/app_state_determinism_test.go b/chain/app/simulation/app_state_determinism_test.go new file mode 100644 index 000000000..6c34ea245 --- /dev/null +++ b/chain/app/simulation/app_state_determinism_test.go @@ -0,0 +1,85 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "math/rand" + "os" + "testing" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + dbm "github.com/tendermint/tm-db" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" +) + +func TestAppStateDeterminism(t *testing.T) { + if !simcli.FlagEnabledValue { + t.Skip("skipping application simulation") + } + + config := simcli.NewConfigFromFlags() + config.InitialBlockHeight = 1 + config.ExportParamsPath = "" + config.OnOperation = false + config.AllInvariants = false + config.ChainID = SimAppChainID + + numSeeds := 3 + numTimesToRunPerSeed := 5 + appHashList := make([]json.RawMessage, numTimesToRunPerSeed) + + for i := 0; i < numSeeds; i++ { + config.Seed = rand.Int63() + + for j := 0; j < numTimesToRunPerSeed; j++ { + var logger log.Logger + if simcli.FlagVerboseValue { + logger = log.TestingLogger() + } else { + logger = log.NewNopLogger() + } + + db := dbm.NewMemDB() + empowerApp := app.New(logger, db, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, interBlockCacheOpt()) + + fmt.Printf( + "running non-determinism simulation; seed %d: %d/%d, attempt: %d/%d\n", + config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + + _, _, err := simulation.SimulateFromSeed( + t, + os.Stdout, + empowerApp.BaseApp, + AppStateFn(empowerApp.AppCodec(), empowerApp.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(empowerApp, empowerApp.AppCodec(), config), + app.BlockedAddresses(), + config, + empowerApp.AppCodec(), + ) + require.NoError(t, err) + + if config.Commit { + simtestutil.PrintStats(db) + } + + appHash := empowerApp.LastCommitID().Hash + appHashList[j] = appHash + + if j != 0 { + require.Equal( + t, string(appHashList[0]), string(appHashList[j]), + "non-determinism in seed %d: %d/%d, attempt: %d/%d\n", config.Seed, i+1, numSeeds, j+1, numTimesToRunPerSeed, + ) + } + } + } +} diff --git a/chain/app/simulation/app_test.go b/chain/app/simulation/app_test.go new file mode 100644 index 000000000..ce07f48fc --- /dev/null +++ b/chain/app/simulation/app_test.go @@ -0,0 +1,56 @@ +package simulation + +import ( + "os" + "testing" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + "github.com/stretchr/testify/require" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" +) + +func TestFullAppSimulation(t *testing.T) { + config := simcli.NewConfigFromFlags() + config.ChainID = SimAppChainID + + db, dir, logger, skip, err := simtestutil.SetupSimulation(config, "empower-chain", "empower-chain-sim", simcli.FlagVerboseValue, simcli.FlagEnabledValue) + if skip { + t.Skip("skipping application simulation") + } + require.NoError(t, err, "simulation setup failed") + + defer func() { + require.NoError(t, db.Close()) + require.NoError(t, os.RemoveAll(dir)) + }() + + empowerApp := app.New(logger, db, nil, true, map[int64]bool{}, app.DefaultNodeHome, simcli.FlagPeriodValue, params.MakeEncodingConfig(app.ModuleBasics), simtestutil.EmptyAppOptions{}, fauxMerkleModeOpt) + require.Equal(t, "empowerchain", empowerApp.Name()) + + // run randomized simulation + _, simParams, simErr := simulation.SimulateFromSeed( + t, + os.Stdout, + empowerApp.BaseApp, + AppStateFn(empowerApp.AppCodec(), empowerApp.SimulationManager()), + simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 + simtestutil.SimulationOperations(empowerApp, empowerApp.AppCodec(), config), + app.BlockedAddresses(), + config, + empowerApp.AppCodec(), + ) + + // export state and simParams before the simulation error is checked + err = simtestutil.CheckExportSimulation(empowerApp, config, simParams) + require.NoError(t, err) + require.NoError(t, simErr) + + if config.Commit { + simtestutil.PrintStats(db) + } +} diff --git a/chain/app/simulation/state.go b/chain/app/simulation/state.go new file mode 100644 index 000000000..c1096ad77 --- /dev/null +++ b/chain/app/simulation/state.go @@ -0,0 +1,257 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "io" + "math/rand" + "os" + "time" + + "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + tmjson "github.com/tendermint/tendermint/libs/json" + tmtypes "github.com/tendermint/tendermint/types" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" +) + +// TODO: Remove this file as soon as a 0.47 release is cut that includes this code in the simtestutil package. + +// Simulation parameter constants +const ( + StakePerAccount = "stake_per_account" + InitiallyBondedValidators = "initially_bonded_validators" +) + +// AppStateFn returns the initial application state using a genesis or the simulation parameters. +// It panics if the user provides files for both of them. +// If a file is not given for the genesis or the sim params, it creates a randomized one. +func AppStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager) simtypes.AppStateFn { + return func(r *rand.Rand, accs []simtypes.Account, config simtypes.Config, + ) (appState json.RawMessage, simAccs []simtypes.Account, chainID string, genesisTimestamp time.Time) { + if simcli.FlagGenesisTimeValue == 0 { + genesisTimestamp = simtypes.RandTimestamp(r) + } else { + genesisTimestamp = time.Unix(simcli.FlagGenesisTimeValue, 0) + } + + chainID = config.ChainID + switch { + case config.ParamsFile != "" && config.GenesisFile != "": + panic("cannot provide both a genesis file and a params file") + + case config.GenesisFile != "": + // override the default chain-id from simapp to set it later to the config + genesisDoc, accounts := AppStateFromGenesisFileFn(r, cdc, config.GenesisFile) + + if simcli.FlagGenesisTimeValue == 0 { + // use genesis timestamp if no custom timestamp is provided (i.e no random timestamp) + genesisTimestamp = genesisDoc.GenesisTime + } + + appState = genesisDoc.AppState + chainID = genesisDoc.ChainID + simAccs = accounts + + case config.ParamsFile != "": + appParams := make(simtypes.AppParams) + bz, err := os.ReadFile(config.ParamsFile) + if err != nil { + panic(err) + } + + err = json.Unmarshal(bz, &appParams) + if err != nil { + panic(err) + } + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + + default: + appParams := make(simtypes.AppParams) + appState, simAccs = AppStateRandomizedFn(simManager, r, cdc, accs, genesisTimestamp, appParams) + } + + rawState := make(map[string]json.RawMessage) + err := json.Unmarshal(appState, &rawState) + if err != nil { + panic(err) + } + + stakingStateBz, ok := rawState[stakingtypes.ModuleName] + if !ok { + panic("staking genesis state is missing") + } + + stakingState := new(stakingtypes.GenesisState) + err = cdc.UnmarshalJSON(stakingStateBz, stakingState) + if err != nil { + panic(err) + } + // compute not bonded balance + notBondedTokens := math.ZeroInt() + for _, val := range stakingState.Validators { + if val.Status != stakingtypes.Unbonded { + continue + } + notBondedTokens = notBondedTokens.Add(val.GetTokens()) + } + notBondedCoins := sdk.NewCoin(stakingState.Params.BondDenom, notBondedTokens) + // edit bank state to make it have the not bonded pool tokens + bankStateBz, ok := rawState[banktypes.ModuleName] + // TODO(fdymylja/jonathan): should we panic in this case + if !ok { + panic("bank genesis state is missing") + } + bankState := new(banktypes.GenesisState) + err = cdc.UnmarshalJSON(bankStateBz, bankState) + if err != nil { + panic(err) + } + + stakingAddr := authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String() + var found bool + for _, balance := range bankState.Balances { + if balance.Address == stakingAddr { + found = true + break + } + } + if !found { + bankState.Balances = append(bankState.Balances, banktypes.Balance{ + Address: stakingAddr, + Coins: sdk.NewCoins(notBondedCoins), + }) + } + + // change appState back + rawState[stakingtypes.ModuleName] = cdc.MustMarshalJSON(stakingState) + rawState[banktypes.ModuleName] = cdc.MustMarshalJSON(bankState) + + // replace appstate + appState, err = json.Marshal(rawState) + if err != nil { + panic(err) + } + return appState, simAccs, chainID, genesisTimestamp + } +} + +// AppStateRandomizedFn creates calls each module's GenesisState generator function +// and creates the simulation params +func AppStateRandomizedFn( + simManager *module.SimulationManager, r *rand.Rand, cdc codec.JSONCodec, + accs []simtypes.Account, genesisTimestamp time.Time, appParams simtypes.AppParams, +) (json.RawMessage, []simtypes.Account) { + numAccs := int64(len(accs)) + genesisState := app.ModuleBasics.DefaultGenesis(cdc) + + // generate a random amount of initial stake coins and a random initial + // number of bonded accounts + var ( + numInitiallyBonded int64 + initialStake math.Int + ) + appParams.GetOrGenerate( + cdc, StakePerAccount, &initialStake, r, + func(r *rand.Rand) { initialStake = math.NewInt(r.Int63n(1e12)) }, + ) + appParams.GetOrGenerate( + cdc, InitiallyBondedValidators, &numInitiallyBonded, r, + func(r *rand.Rand) { numInitiallyBonded = int64(r.Intn(300)) }, + ) + + if numInitiallyBonded > numAccs { + numInitiallyBonded = numAccs + } + + fmt.Printf( + `Selected randomly generated parameters for simulated genesis: +{ + stake_per_account: "%d", + initially_bonded_validators: "%d" +} +`, initialStake, numInitiallyBonded, + ) + + simState := &module.SimulationState{ + AppParams: appParams, + Cdc: cdc, + Rand: r, + GenState: genesisState, + Accounts: accs, + InitialStake: initialStake, + NumBonded: numInitiallyBonded, + GenTimestamp: genesisTimestamp, + BondDenom: params.DefaultBondDenom, + } + + simManager.GenerateGenesisStates(simState) + + appState, err := json.Marshal(genesisState) + if err != nil { + panic(err) + } + + return appState, accs +} + +// AppStateFromGenesisFileFn util function to generate the genesis AppState +// from a genesis.json file. +func AppStateFromGenesisFileFn(r io.Reader, cdc codec.JSONCodec, genesisFile string) (tmtypes.GenesisDoc, []simtypes.Account) { + bytes, err := os.ReadFile(genesisFile) + if err != nil { + panic(err) + } + + var genesis tmtypes.GenesisDoc + // NOTE: Tendermint uses a custom JSON decoder for GenesisDoc + err = tmjson.Unmarshal(bytes, &genesis) + if err != nil { + panic(err) + } + + var appState app.GenesisState + err = json.Unmarshal(genesis.AppState, &appState) + if err != nil { + panic(err) + } + + var authGenesis authtypes.GenesisState + if appState[authtypes.ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[authtypes.ModuleName], &authGenesis) + } + + newAccs := make([]simtypes.Account, len(authGenesis.Accounts)) + for i, acc := range authGenesis.Accounts { + // Pick a random private key, since we don't know the actual key + // This should be fine as it's only used for mock Tendermint validators + // and these keys are never actually used to sign by mock Tendermint. + privkeySeed := make([]byte, 15) + if _, err := r.Read(privkeySeed); err != nil { + panic(err) + } + + privKey := secp256k1.GenPrivKeyFromSecret(privkeySeed) + + a, ok := acc.GetCachedValue().(authtypes.AccountI) + if !ok { + panic("expected account") + } + + // create simulator accounts + simAcc := simtypes.Account{PrivKey: privKey, PubKey: privKey.PubKey(), Address: a.GetAddress()} + newAccs[i] = simAcc + } + + return genesis, newAccs +} diff --git a/chain/app/simulation/utils.go b/chain/app/simulation/utils.go new file mode 100644 index 000000000..877ecb0a7 --- /dev/null +++ b/chain/app/simulation/utils.go @@ -0,0 +1,33 @@ +package simulation + +import ( + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + simcli "github.com/cosmos/cosmos-sdk/x/simulation/client/cli" +) + +const SimAppChainID = "empower-chain-sim-chain-id" + +type StoreKeysPrefixes struct { + A storetypes.StoreKey + B storetypes.StoreKey + Prefixes [][]byte +} + +// Get flags every time the simulator is run +func init() { + simcli.GetSimulatorFlags() +} + +// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of +// an IAVLStore for faster simulation speed. +func fauxMerkleModeOpt(bapp *baseapp.BaseApp) { + bapp.SetFauxMerkleMode() +} + +// interBlockCacheOpt returns a BaseApp option function that sets the persistent +// inter-block write-through cache. +func interBlockCacheOpt() func(*baseapp.BaseApp) { + return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager()) +} diff --git a/chain/proto/empowerchain/plasticcredit/query.proto b/chain/proto/empowerchain/plasticcredit/query.proto index 89559c138..dccf712d0 100644 --- a/chain/proto/empowerchain/plasticcredit/query.proto +++ b/chain/proto/empowerchain/plasticcredit/query.proto @@ -21,6 +21,10 @@ service Query { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/issuers/{issuer_id}"; } + rpc Applicants(QueryApplicantsRequest) returns (QueryApplicantsResponse) { + option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/applicants"; + } + rpc Applicant(QueryApplicantRequest) returns (QueryApplicantResponse) { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/applicants/{applicant_id}"; } @@ -33,6 +37,10 @@ service Query { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/credit-classes/{credit_class_abbreviation}"; } + rpc Projects(QueryProjectsRequest) returns (QueryProjectsResponse) { + option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/projects"; + } + rpc Project(QueryProjectRequest) returns (QueryProjectResponse) { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/projects/{project_id}"; } @@ -41,6 +49,10 @@ service Query { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/creditcollections/{denom}"; } + rpc CreditBalances(QueryCreditBalancesRequest) returns (QueryCreditBalancesResponse) { + option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/creditbalances"; + } + rpc CreditBalance(QueryCreditBalanceRequest) returns (QueryCreditBalanceResponse) { option (google.api.http).get = "/empowerchain/empowerchain/plasticcredit/creditbalances/{owner}/{denom}"; } @@ -69,6 +81,15 @@ message QueryIssuerResponse { Issuer issuer = 1 [(gogoproto.nullable) = false]; } +message QueryApplicantsRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1 [(gogoproto.nullable) = false]; +} + +message QueryApplicantsResponse { + repeated Applicant applicants = 1 [(gogoproto.nullable) = false]; + cosmos.base.query.v1beta1.PageResponse pagination = 2 [(gogoproto.nullable) = false]; +} + message QueryApplicantRequest { uint64 applicant_id = 1; } @@ -94,6 +115,15 @@ message QueryCreditClassResponse { CreditClass credit_class = 1 [(gogoproto.nullable) = false]; } +message QueryProjectsRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1 [(gogoproto.nullable) = false]; +} + +message QueryProjectsResponse { + repeated Project projects = 1 [(gogoproto.nullable) = false]; + cosmos.base.query.v1beta1.PageResponse pagination = 2 [(gogoproto.nullable) = false]; +} + message QueryProjectRequest { uint64 project_id = 1; } @@ -110,6 +140,15 @@ message QueryCreditCollectionResponse { CreditCollection credit_collection = 1 [(gogoproto.nullable) = false]; } +message QueryCreditBalancesRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1 [(gogoproto.nullable) = false]; +} + +message QueryCreditBalancesResponse { + repeated CreditBalance credit_balances = 1 [(gogoproto.nullable) = false]; + cosmos.base.query.v1beta1.PageResponse pagination = 2 [(gogoproto.nullable) = false]; +} + message QueryCreditBalanceRequest { string owner = 1; string denom = 2; diff --git a/chain/proto/empowerchain/plasticcredit/tx.proto b/chain/proto/empowerchain/plasticcredit/tx.proto index 9dc068891..f3e638c09 100644 --- a/chain/proto/empowerchain/plasticcredit/tx.proto +++ b/chain/proto/empowerchain/plasticcredit/tx.proto @@ -61,7 +61,7 @@ service Msg { message MsgUpdateParams { option (cosmos.msg.v1.signer) = "authority"; - // authority is the address of the governance account. + // authority is the address that controls the module (defaults to x/gov unless overwritten in keeper). string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // params defines the x/plasitccredit parameters to update. diff --git a/chain/utils/validation.go b/chain/utils/validation.go index 47711e9bb..f124271de 100644 --- a/chain/utils/validation.go +++ b/chain/utils/validation.go @@ -9,7 +9,7 @@ var ( // Matches the regex for a valid name, which is: // - 2-64 characters long // - does not start or end with a space - basicNameValidation = regexp.MustCompile(`^\S.{1,62}\S$`) + basicNameValidation = regexp.MustCompile(`^\S.{0,62}\S$`) // Matches the regex for a valid description, which is: // - up to 256 characters diff --git a/chain/utils/validation_test.go b/chain/utils/validation_test.go index 10faad737..c61e248b1 100644 --- a/chain/utils/validation_test.go +++ b/chain/utils/validation_test.go @@ -21,10 +21,18 @@ func TestIsBasicValidName(t *testing.T) { name: "also OK_78%$", expectedResult: true, }, + "Happy path 3": { + name: "fx", + expectedResult: true, + }, "Happy path full length:": { name: "This name is 64 characters long, which is the limit we have set!", expectedResult: true, }, + "Too short name should fail": { + name: "f", + expectedResult: false, + }, "Too long name should fail": { name: "This name is 65 characters long, which is above the limit we set!", expectedResult: false, diff --git a/chain/x/plasticcredit/errors.go b/chain/x/plasticcredit/errors.go index 90d0f1683..9f91c3917 100644 --- a/chain/x/plasticcredit/errors.go +++ b/chain/x/plasticcredit/errors.go @@ -47,6 +47,7 @@ var ( ErrCreditsNotEnough = errors.Register(ModuleName, 7001, "not enough credits") ErrActiveCreditsNotEnough = errors.Register(ModuleName, 7002, "not enough active credits") + ErrSameSenderAndRecipient = errors.Register(ModuleName, 7003, "sender and recipient are the same") ErrCreditBalanceNotFound = errors.Register(ModuleName, 7404, "credit balance not found") ErrCreditBalanceDuplicate = errors.Register(ModuleName, 7409, "duplicate credit balance detected") ) diff --git a/chain/x/plasticcredit/genesis.go b/chain/x/plasticcredit/genesis.go index d9307a07b..873c0fdd9 100644 --- a/chain/x/plasticcredit/genesis.go +++ b/chain/x/plasticcredit/genesis.go @@ -93,7 +93,7 @@ func (gs GenesisState) Validate() error { } if _, exists := projects[project.Id]; exists { - return errors.Wrapf(ErrProjectDuplicate, "duplicate project ith id %d was found", project.Id) + return errors.Wrapf(ErrProjectDuplicate, "duplicate project with id %d was found", project.Id) } projects[project.Id] = project } diff --git a/chain/x/plasticcredit/keeper/applicant.go b/chain/x/plasticcredit/keeper/applicant.go index fbeb2eac0..ce2e81f98 100644 --- a/chain/x/plasticcredit/keeper/applicant.go +++ b/chain/x/plasticcredit/keeper/applicant.go @@ -6,6 +6,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" ) @@ -24,6 +25,26 @@ func (k Keeper) GetApplicant(ctx sdk.Context, id uint64) (applicant plasticcredi return applicant, true } +func (k Keeper) GetApplicants(ctx sdk.Context, pageReq query.PageRequest) ([]plasticcredit.Applicant, query.PageResponse, error) { + store := k.getApplicantStore(ctx) + + var applicants []plasticcredit.Applicant + pageRes, err := query.Paginate(store, &pageReq, func(_ []byte, value []byte) error { + var applicant plasticcredit.Applicant + if err := k.cdc.Unmarshal(value, &applicant); err != nil { + return err + } + applicants = append(applicants, applicant) + + return nil + }) + if err != nil { + return nil, query.PageResponse{}, err + } + + return applicants, *pageRes, nil +} + func (k Keeper) createApplicant(ctx sdk.Context, name string, description string, admin string) (uint64, error) { idc := k.GetIDCounters(ctx) diff --git a/chain/x/plasticcredit/keeper/credit.go b/chain/x/plasticcredit/keeper/credit.go index f722da9e4..e7b8a2bfb 100644 --- a/chain/x/plasticcredit/keeper/credit.go +++ b/chain/x/plasticcredit/keeper/credit.go @@ -8,6 +8,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/gogoproto/proto" "github.com/EmpowerPlastic/empowerchain/utils" @@ -42,6 +43,26 @@ func (k Keeper) GetCreditBalance(ctx sdk.Context, owner sdk.AccAddress, denom st return creditBalance, true } +func (k Keeper) GetCreditBalances(ctx sdk.Context, pageReq query.PageRequest) ([]plasticcredit.CreditBalance, query.PageResponse, error) { + store := k.getCreditBalanceStore(ctx) + + var creditBalances []plasticcredit.CreditBalance + pageRes, err := query.Paginate(store, &pageReq, func(_ []byte, value []byte) error { + var creditBalance plasticcredit.CreditBalance + if err := k.cdc.Unmarshal(value, &creditBalance); err != nil { + return err + } + creditBalances = append(creditBalances, creditBalance) + + return nil + }) + if err != nil { + return nil, query.PageResponse{}, err + } + + return creditBalances, *pageRes, nil +} + func (k Keeper) retireCreditsForAddress(ctx sdk.Context, owner sdk.AccAddress, denom string, amount uint64) (plasticcredit.CreditBalance, error) { creditBalance, found := k.GetCreditBalance(ctx, owner, denom) if !found { @@ -104,42 +125,44 @@ func (k Keeper) transferCredits(ctx sdk.Context, denom string, from sdk.AccAddre return errors.Wrapf(plasticcredit.ErrCreditsNotEnough, "sender only has %d credits of denom %s", balanceSender.Balance.Active, denom) } - var balanceRecipient *plasticcredit.CreditBalance if from.Equals(to) { - balanceRecipient = &balanceSender - } else { - rec, found := k.GetCreditBalance(ctx, to, denom) - if !found { - rec = plasticcredit.CreditBalance{ - Owner: to.String(), - Denom: denom, - Balance: plasticcredit.CreditAmount{ - Active: 0, - Retired: 0, - }, - } + return errors.Wrapf(plasticcredit.ErrSameSenderAndRecipient, "sender and recipient are the same") + } + + balanceRecipient, found := k.GetCreditBalance(ctx, to, denom) + if !found { + // Create a new, empty one if not found + balanceRecipient = plasticcredit.CreditBalance{ + Owner: to.String(), + Denom: denom, + Balance: plasticcredit.CreditAmount{ + Active: 0, + Retired: 0, + }, } - balanceRecipient = &rec } balanceSender.Balance.Active -= amount + // If retiring credits, retire and update retired balance, if not, update active balance if retire { - err := k.retireCreditsInCollection(ctx, denom, amount) - if err != nil { + if err := k.retireCreditsInCollection(ctx, denom, amount); err != nil { return err } balanceRecipient.Balance.Retired += amount } else { balanceRecipient.Balance.Active += amount } + err := k.setCreditBalance(ctx, balanceSender) if err != nil { return err } - err = k.setCreditBalance(ctx, *balanceRecipient) + + err = k.setCreditBalance(ctx, balanceRecipient) if err != nil { return err } + abbrev, _ := SplitCreditDenom(denom) creditClass, found := k.GetCreditClass(ctx, abbrev) if !found { diff --git a/chain/x/plasticcredit/keeper/invariants.go b/chain/x/plasticcredit/keeper/invariants.go index 0d7c6187a..b1d67eedb 100644 --- a/chain/x/plasticcredit/keeper/invariants.go +++ b/chain/x/plasticcredit/keeper/invariants.go @@ -36,19 +36,15 @@ func TotalSupplyInvariant(k InvariantKeeper) sdk.Invariant { Retired uint64 }) k.IterateCreditBalances(ctx, func(creditBalance plasticcredit.CreditBalance) { - if totalSupply, ok := totalSupplies[creditBalance.Denom]; ok { - totalSupply.Active += creditBalance.Balance.Active - totalSupply.Retired += creditBalance.Balance.Retired - totalSupplies[creditBalance.Denom] = totalSupply - } else { - totalSupply.Active = creditBalance.Balance.Active - totalSupply.Retired = creditBalance.Balance.Retired - totalSupplies[creditBalance.Denom] = totalSupply - } + totalSupply := totalSupplies[creditBalance.Denom] + totalSupply.Active += creditBalance.Balance.Active + totalSupply.Retired += creditBalance.Balance.Retired + totalSupplies[creditBalance.Denom] = totalSupply }) k.IterateCreditCollections(ctx, func(creditCollection plasticcredit.CreditCollection) { - if totalSupplies[creditCollection.Denom].Active != creditCollection.TotalAmount.Active || totalSupplies[creditCollection.Denom].Retired != creditCollection.TotalAmount.Retired { + if totalSupplies[creditCollection.Denom].Active != creditCollection.TotalAmount.Active || + totalSupplies[creditCollection.Denom].Retired != creditCollection.TotalAmount.Retired { count++ msg += fmt.Sprintf("%s collection has %d active and %d retired credits, but the total of active is %d and retired is %d\n", creditCollection.Denom, creditCollection.TotalAmount.Active, creditCollection.TotalAmount.Retired, totalSupplies[creditCollection.Denom].Active, totalSupplies[creditCollection.Denom].Retired) } diff --git a/chain/x/plasticcredit/keeper/keeper_test.go b/chain/x/plasticcredit/keeper/keeper_test.go index e58db5a4f..c712428d8 100644 --- a/chain/x/plasticcredit/keeper/keeper_test.go +++ b/chain/x/plasticcredit/keeper/keeper_test.go @@ -46,11 +46,6 @@ func (s *TestSuite) SetupTest() { ctx := empowerApp.BaseApp.NewContext(false, tmproto.Header{}) ctx = ctx.WithBlockHeader(tmproto.Header{Time: tmtime.Now()}) - //TODO: - /*queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) - nft.RegisterQueryServer(queryHelper, app.NFTKeeper) - queryClient := nft.NewQueryClient(queryHelper)*/ - s.empowerApp = empowerApp s.ctx = ctx s.addrs = app.CreateRandomAccounts(1) diff --git a/chain/x/plasticcredit/keeper/msg_server_test.go b/chain/x/plasticcredit/keeper/msg_server_test.go index ec89fa6bc..e69c6ff04 100644 --- a/chain/x/plasticcredit/keeper/msg_server_test.go +++ b/chain/x/plasticcredit/keeper/msg_server_test.go @@ -1448,10 +1448,10 @@ func (s *TestSuite) TestTransferCredits() { Amount: 100, Retire: false, }, - expectedSenderBalance: 100000000, - expectedRecipientBalanceActive: 100000000, + expectedSenderBalance: 0, + expectedRecipientBalanceActive: 0, expectedRecipientBalanceRetired: 0, - err: nil, + err: plasticcredit.ErrSameSenderAndRecipient, }, "sending to the same address (no balance)": { msg: &plasticcredit.MsgTransferCredits{ diff --git a/chain/x/plasticcredit/keeper/project.go b/chain/x/plasticcredit/keeper/project.go index a258c8929..9683aee20 100644 --- a/chain/x/plasticcredit/keeper/project.go +++ b/chain/x/plasticcredit/keeper/project.go @@ -6,6 +6,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" ) @@ -23,6 +24,26 @@ func (k Keeper) GetProject(ctx sdk.Context, projectID uint64) (project plasticcr return project, true } +func (k Keeper) GetProjects(ctx sdk.Context, pageReq query.PageRequest) ([]plasticcredit.Project, query.PageResponse, error) { + store := k.getProjectStore(ctx) + + var projects []plasticcredit.Project + pageRes, err := query.Paginate(store, &pageReq, func(_ []byte, value []byte) error { + var project plasticcredit.Project + if err := k.cdc.Unmarshal(value, &project); err != nil { + return err + } + projects = append(projects, project) + + return nil + }) + if err != nil { + return nil, query.PageResponse{}, err + } + + return projects, *pageRes, nil +} + func (k Keeper) CreateProject(ctx sdk.Context, creator sdk.AccAddress, applicantID uint64, creditClassAbbreviation string, name string) (uint64, error) { applicant, found := k.GetApplicant(ctx, applicantID) if !found { diff --git a/chain/x/plasticcredit/keeper/query_server.go b/chain/x/plasticcredit/keeper/query_server.go index d28a67e09..1c8a71cfb 100644 --- a/chain/x/plasticcredit/keeper/query_server.go +++ b/chain/x/plasticcredit/keeper/query_server.go @@ -61,6 +61,23 @@ func (k Querier) Issuer(goCtx context.Context, req *plasticcredit.QueryIssuerReq }, nil } +func (k Querier) Applicants(goCtx context.Context, req *plasticcredit.QueryApplicantsRequest) (*plasticcredit.QueryApplicantsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + applicants, pageRes, err := k.GetApplicants(ctx, req.Pagination) + if err != nil { + return nil, err + } + + return &plasticcredit.QueryApplicantsResponse{ + Applicants: applicants, + Pagination: pageRes, + }, nil +} + func (k Querier) Applicant(goCtx context.Context, req *plasticcredit.QueryApplicantRequest) (*plasticcredit.QueryApplicantResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -110,6 +127,23 @@ func (k Querier) CreditClass(goCtx context.Context, req *plasticcredit.QueryCred }, nil } +func (k Querier) Projects(goCtx context.Context, req *plasticcredit.QueryProjectsRequest) (*plasticcredit.QueryProjectsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + projects, pageRes, err := k.GetProjects(ctx, req.Pagination) + if err != nil { + return nil, err + } + + return &plasticcredit.QueryProjectsResponse{ + Projects: projects, + Pagination: pageRes, + }, nil +} + func (k Querier) Project(goCtx context.Context, req *plasticcredit.QueryProjectRequest) (*plasticcredit.QueryProjectResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -142,6 +176,23 @@ func (k Querier) CreditCollection(goCtx context.Context, req *plasticcredit.Quer }, nil } +func (k Querier) CreditBalances(goCtx context.Context, req *plasticcredit.QueryCreditBalancesRequest) (*plasticcredit.QueryCreditBalancesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + creditBalances, pageRes, err := k.GetCreditBalances(ctx, req.Pagination) + if err != nil { + return nil, err + } + + return &plasticcredit.QueryCreditBalancesResponse{ + CreditBalances: creditBalances, + Pagination: pageRes, + }, nil +} + func (k Querier) CreditBalance(goCtx context.Context, req *plasticcredit.QueryCreditBalanceRequest) (*plasticcredit.QueryCreditBalanceResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") diff --git a/chain/x/plasticcredit/keeper/query_server_test.go b/chain/x/plasticcredit/keeper/query_server_test.go index 191b587c5..0e39d903e 100644 --- a/chain/x/plasticcredit/keeper/query_server_test.go +++ b/chain/x/plasticcredit/keeper/query_server_test.go @@ -112,6 +112,53 @@ func (s *TestSuite) TestIssuersQuery() { s.Require().Len(resp3.Issuers, 10) } +func (s *TestSuite) TestApplicantsQuery() { + k := s.empowerApp.PlasticcreditKeeper + goCtx := sdk.WrapSDKContext(s.ctx) + + querier := keeper.Querier{Keeper: k} + resp, err := querier.Applicants(goCtx, &plasticcredit.QueryApplicantsRequest{}) + s.Require().NoError(err) + s.Require().Len(resp.Applicants, 0) + + ms := keeper.NewMsgServerImpl(k) + baseName := "Empower" + description := "Something description." + admin := sample.AccAddress() + for i := 0; i < 11; i++ { + id := i + 1 + createMsg := plasticcredit.MsgCreateApplicant{ + Name: fmt.Sprintf("%s%d", baseName, id), + Description: description, + Admin: admin, + } + _, err = ms.CreateApplicant(goCtx, &createMsg) + s.Require().NoError(err) + } + + resp2, err := querier.Applicants(goCtx, &plasticcredit.QueryApplicantsRequest{}) + s.Require().NoError(err) + s.Require().Len(resp2.Applicants, 11) + + for i, applicant := range resp2.Applicants { + id := i + 1 + s.Require().Equal(uint64(id), applicant.Id) + expectedName := fmt.Sprintf("%s%d", baseName, id) + s.Require().Equal(expectedName, applicant.Name) + s.Require().Equal(description, applicant.Description) + s.Require().Equal(admin, applicant.Admin) + } + + resp3, err := querier.Applicants(goCtx, &plasticcredit.QueryApplicantsRequest{ + Pagination: query.PageRequest{ + Offset: 0, + Limit: 10, + }, + }) + s.Require().NoError(err) + s.Require().Len(resp3.Applicants, 10) +} + func (s *TestSuite) TestApplicantQuery() { k := s.empowerApp.PlasticcreditKeeper goCtx := sdk.WrapSDKContext(s.ctx) @@ -154,7 +201,7 @@ func (s *TestSuite) TestCreditClassQuery() { Admin: issuerAdmin, }) s.Require().NoError(err) - creditClassAbbreviation := "PCRD" + creditClassAbbreviation := "CRDT" querier := keeper.Querier{Keeper: k} _, err = querier.CreditClass(goCtx, &plasticcredit.QueryCreditClassRequest{ @@ -238,6 +285,80 @@ func (s *TestSuite) TestCreditClassesQuery() { s.Require().Len(resp3.CreditClasses, 10) } +func (s *TestSuite) TestProjectsQuery() { + k := s.empowerApp.PlasticcreditKeeper + goCtx := sdk.WrapSDKContext(s.ctx) + ms := keeper.NewMsgServerImpl(k) + issuerAdmin := sample.AccAddress() + // fund the issuerAdmin account for fee + s.fundAccount(issuerAdmin, sdk.NewCoins(sdk.NormalizeCoin(sdk.NewCoin(params.HumanCoinDenom, sdk.NewInt(10e6))))) + applicantAdmin := sample.AccAddress() + creditClassAbbreviation := "DRP" + _, err := ms.CreateIssuer(goCtx, &plasticcredit.MsgCreateIssuer{ + Creator: k.Authority(), + Name: "Empower", + Description: "Something", + Admin: issuerAdmin, + }) + s.Require().NoError(err) + _, err = ms.CreateCreditClass(goCtx, &plasticcredit.MsgCreateCreditClass{ + Creator: issuerAdmin, + Abbreviation: creditClassAbbreviation, + IssuerId: 1, + Name: "Empower Plastic Credits", + }) + s.Require().NoError(err) + _, err = ms.CreateApplicant(goCtx, &plasticcredit.MsgCreateApplicant{ + Admin: applicantAdmin, + Name: "Empower", + Description: "Something", + }) + s.Require().NoError(err) + + querier := keeper.Querier{Keeper: k} + resp, err := querier.Projects(goCtx, &plasticcredit.QueryProjectsRequest{}) + s.Require().NoError(err) + s.Require().Len(resp.Projects, 0) + + var expectedProjects []plasticcredit.Project + for i := 0; i < 11; i++ { + abbreviation := fmt.Sprintf("ABC%d", i) + name := fmt.Sprintf("Empower Project (%s)", abbreviation) + + createMsg := plasticcredit.MsgCreateProject{ + Creator: applicantAdmin, + ApplicantId: 1, + Name: name, + CreditClassAbbreviation: creditClassAbbreviation, + } + _, err = ms.CreateProject(goCtx, &createMsg) + s.Require().NoError(err) + + expectedProjects = append(expectedProjects, plasticcredit.Project{ + Id: uint64(i + 1), + ApplicantId: createMsg.ApplicantId, + CreditClassAbbreviation: creditClassAbbreviation, + Name: createMsg.Name, + Status: plasticcredit.ProjectStatus_NEW, + }) + } + + resp2, err := querier.Projects(goCtx, &plasticcredit.QueryProjectsRequest{}) + s.Require().NoError(err) + s.Require().Len(resp2.Projects, 11) + + s.Require().ElementsMatch(expectedProjects, resp2.Projects) + + resp3, err := querier.Projects(goCtx, &plasticcredit.QueryProjectsRequest{ + Pagination: query.PageRequest{ + Offset: 0, + Limit: 10, + }, + }) + s.Require().NoError(err) + s.Require().Len(resp3.Projects, 10) +} + func (s *TestSuite) TestProjectQuery() { k := s.empowerApp.PlasticcreditKeeper goCtx := sdk.WrapSDKContext(s.ctx) @@ -295,4 +416,104 @@ func (s *TestSuite) TestProjectQuery() { s.Require().Equal(plasticcredit.ProjectStatus_NEW, resp.Project.Status) } -// TODO credit balance, credit collection queries +func (s *TestSuite) TestCreditCollectionQuery() { + s.PopulateWithSamples() + + k := s.empowerApp.PlasticcreditKeeper + goCtx := sdk.WrapSDKContext(s.ctx) + querier := keeper.Querier{Keeper: k} + + _, err := querier.CreditCollection(goCtx, &plasticcredit.QueryCreditCollectionRequest{ + Denom: "notexists", + }) + s.Require().ErrorIs(err, plasticcredit.ErrCreditCollectionNotFound) + + resp, err := querier.CreditCollection(goCtx, &plasticcredit.QueryCreditCollectionRequest{ + Denom: s.sampleCreditDenom, + }) + s.Require().NoError(err) + s.Require().Equal(s.sampleCreditDenom, resp.CreditCollection.Denom) +} + +func (s *TestSuite) TestCreditBalanceQuery() { + s.PopulateWithSamples() + + k := s.empowerApp.PlasticcreditKeeper + goCtx := sdk.WrapSDKContext(s.ctx) + querier := keeper.Querier{Keeper: k} + sampleOwner := sample.AccAddress() + + _, err := querier.CreditBalance(goCtx, &plasticcredit.QueryCreditBalanceRequest{ + Denom: "notexists", + Owner: sampleOwner, + }) + s.Require().ErrorIs(err, plasticcredit.ErrCreditBalanceNotFound) + + // Also not found even if the denom exists, but the "owner" doesn't have any balance + _, err = querier.CreditBalance(goCtx, &plasticcredit.QueryCreditBalanceRequest{ + Denom: s.sampleCreditDenom, + Owner: sampleOwner, + }) + s.Require().ErrorIs(err, plasticcredit.ErrCreditBalanceNotFound) + + // Now let's create a balance + ms := keeper.NewMsgServerImpl(k) + _, err = ms.TransferCredits(goCtx, &plasticcredit.MsgTransferCredits{ + From: s.sampleApplicantAdmin, + To: sampleOwner, + Denom: s.sampleCreditDenom, + Amount: 1337, + Retire: false, + }) + s.Require().NoError(err) + + resp, err := querier.CreditBalance(goCtx, &plasticcredit.QueryCreditBalanceRequest{ + Denom: s.sampleCreditDenom, + Owner: sampleOwner, + }) + s.Require().NoError(err) + s.Require().Equal(s.sampleCreditDenom, resp.Balance.Denom) + s.Require().Equal(sampleOwner, resp.Balance.Owner) + s.Require().Equal(uint64(1337), resp.Balance.Balance.Active) + s.Require().Equal(uint64(0), resp.Balance.Balance.Retired) +} + +func (s *TestSuite) TestCreditBalancesQuery() { + s.PopulateWithSamples() + + k := s.empowerApp.PlasticcreditKeeper + goCtx := sdk.WrapSDKContext(s.ctx) + querier := keeper.Querier{Keeper: k} + + resp1, err := querier.CreditBalances(goCtx, &plasticcredit.QueryCreditBalancesRequest{}) + s.Require().NoError(err) + s.Require().Equal(1, len(resp1.CreditBalances)) + + // Now, let's transfer some credits to other accounts, so we get a bunch of balances to query + ms := keeper.NewMsgServerImpl(k) + for i := 0; i < 11; i++ { + recipient := sample.AccAddress() + _, err = ms.TransferCredits(goCtx, &plasticcredit.MsgTransferCredits{ + From: s.sampleApplicantAdmin, + To: recipient, + Denom: s.sampleCreditDenom, + Amount: 1337, + Retire: false, + }) + s.Require().NoError(err) + } + + resp2, err := querier.CreditBalances(goCtx, &plasticcredit.QueryCreditBalancesRequest{}) + s.Require().NoError(err) + s.Require().Equal(12, len(resp2.CreditBalances)) + + // Now, let's query with pagination + resp3, err := querier.CreditBalances(goCtx, &plasticcredit.QueryCreditBalancesRequest{ + Pagination: query.PageRequest{ + Limit: 5, + Offset: 0, + }, + }) + s.Require().NoError(err) + s.Require().Equal(5, len(resp3.CreditBalances)) +} diff --git a/chain/x/plasticcredit/module/module.go b/chain/x/plasticcredit/module/module.go index c3f5cc49d..172fd1839 100644 --- a/chain/x/plasticcredit/module/module.go +++ b/chain/x/plasticcredit/module/module.go @@ -30,11 +30,7 @@ var ( // AppModuleBasic implements the AppModuleBasic interface that defines the independent methods a Cosmos SDK module needs to implement. type AppModuleBasic struct { - cdc codec.BinaryCodec -} - -func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic { - return AppModuleBasic{cdc: cdc} + cdc codec.Codec } // Name returns the name of the module as a string @@ -93,16 +89,22 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { type AppModule struct { AppModuleBasic - keeper keeper.Keeper + keeper keeper.Keeper + accountKeeper plasticcredit.AccountKeeper + bankKeeper plasticcredit.BankKeeper } func NewAppModule( cdc codec.Codec, keeper keeper.Keeper, + ak plasticcredit.AccountKeeper, + bk plasticcredit.BankKeeper, ) AppModule { return AppModule{ - AppModuleBasic: NewAppModuleBasic(cdc), + AppModuleBasic: AppModuleBasic{cdc: cdc}, keeper: keeper, + accountKeeper: ak, + bankKeeper: bk, } } diff --git a/chain/x/plasticcredit/module/module_simulation.go b/chain/x/plasticcredit/module/module_simulation.go index 96fef501c..f3409c061 100644 --- a/chain/x/plasticcredit/module/module_simulation.go +++ b/chain/x/plasticcredit/module/module_simulation.go @@ -1,58 +1,37 @@ package module import ( - "math/rand" - - "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/simulation" - "github.com/EmpowerPlastic/empowerchain/testutil/sample" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/simulation" ) -// avoid unused import issue var ( - _ = sample.AccAddress - _ = simulation.MsgEntryKind - _ = baseapp.Paramspace + _ module.AppModuleSimulation = AppModule{} + _ module.HasProposalMsgs = AppModule{} ) // GenerateGenesisState creates a randomized GenState of the module func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - accs := make([]string, len(simState.Accounts)) - for i, acc := range simState.Accounts { - accs[i] = acc.Address.String() - } - plasticcreditGenesis := types.GenesisState{ - Params: types.DefaultParams(), - } - simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(&plasticcreditGenesis) + simulation.RandomizedGenState(simState) } -// ProposalContents doesn't return any content functions for governance proposals -func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalMsg { - return nil +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + return simulation.ProposalMsgs() } -// RandomizedParams creates randomized param changes for the simulator -func (am AppModule) RandomizedParams(_ *rand.Rand) []simtypes.LegacyParamChange { - // plasticcreditParams := types.DefaultParams() - return []simtypes.LegacyParamChange{ - /*simulation.NewSimParamChange(types.ModuleName, string(types.KeyCreateissuerAllowlist), func(r *rand.Rand) string { - return string(types.Amino.MustMarshalJSON(plasticcreditParams.CreateissuerAllowlist)) - }),*/ - } +// RegisterStoreDecoder registers a decoder for plasticcredit module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[plasticcredit.StoreKey] = simulation.NewDecodeStore(am.cdc) } -// RegisterStoreDecoder registers a decoder -func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {} - -// WeightedOperations returns the all the gov module operations with their respective weights. +// WeightedOperations returns the all the plasticcredit module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { - operations := make([]simtypes.WeightedOperation, 0) - - return operations + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, am.accountKeeper, am.bankKeeper, am.keeper, + ) } diff --git a/chain/x/plasticcredit/msgs.go b/chain/x/plasticcredit/msgs.go index 637015c7d..fb97af679 100644 --- a/chain/x/plasticcredit/msgs.go +++ b/chain/x/plasticcredit/msgs.go @@ -30,9 +30,12 @@ func (m *MsgUpdateParams) ValidateBasic() error { return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid authority address (%s)", err) } - _, err = sdk.AccAddressFromBech32(m.Params.IssuerCreator) - if err != nil { - return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid issuer creator address (%s)", err) + // We allow empty issuer creator (which means only gov can create issuers) + if m.Params.IssuerCreator != "" { + _, err = sdk.AccAddressFromBech32(m.Params.IssuerCreator) + if err != nil { + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid issuer creator address (%s)", err) + } } return m.Params.Validate() diff --git a/chain/x/plasticcredit/msgs_test.go b/chain/x/plasticcredit/msgs_test.go index c14ba26fb..4fd959440 100644 --- a/chain/x/plasticcredit/msgs_test.go +++ b/chain/x/plasticcredit/msgs_test.go @@ -29,6 +29,16 @@ func TestMsgUpdateParams_ValidateBasic(t *testing.T) { }, expectedError: nil, }, + "happy path - no issuer creator": { + msgUnderTest: &MsgUpdateParams{ + Authority: sample.AccAddress(), + Params: Params{ + IssuerCreator: "", + CreditClassCreationFee: sdk.NewCoin(params.BaseCoinDenom, sdk.NewInt(rand.Int63())), + }, + }, + expectedError: nil, + }, "invalid authority": { msgUnderTest: &MsgUpdateParams{ Authority: "invalid", diff --git a/chain/x/plasticcredit/query.pb.go b/chain/x/plasticcredit/query.pb.go index 69f4c9d37..8e66db5f7 100644 --- a/chain/x/plasticcredit/query.pb.go +++ b/chain/x/plasticcredit/query.pb.go @@ -294,6 +294,102 @@ func (m *QueryIssuerResponse) GetIssuer() Issuer { return Issuer{} } +type QueryApplicantsRequest struct { + Pagination query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryApplicantsRequest) Reset() { *m = QueryApplicantsRequest{} } +func (m *QueryApplicantsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryApplicantsRequest) ProtoMessage() {} +func (*QueryApplicantsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{6} +} +func (m *QueryApplicantsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryApplicantsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryApplicantsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryApplicantsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryApplicantsRequest.Merge(m, src) +} +func (m *QueryApplicantsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryApplicantsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryApplicantsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryApplicantsRequest proto.InternalMessageInfo + +func (m *QueryApplicantsRequest) GetPagination() query.PageRequest { + if m != nil { + return m.Pagination + } + return query.PageRequest{} +} + +type QueryApplicantsResponse struct { + Applicants []Applicant `protobuf:"bytes,1,rep,name=applicants,proto3" json:"applicants"` + Pagination query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryApplicantsResponse) Reset() { *m = QueryApplicantsResponse{} } +func (m *QueryApplicantsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryApplicantsResponse) ProtoMessage() {} +func (*QueryApplicantsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{7} +} +func (m *QueryApplicantsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryApplicantsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryApplicantsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryApplicantsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryApplicantsResponse.Merge(m, src) +} +func (m *QueryApplicantsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryApplicantsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryApplicantsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryApplicantsResponse proto.InternalMessageInfo + +func (m *QueryApplicantsResponse) GetApplicants() []Applicant { + if m != nil { + return m.Applicants + } + return nil +} + +func (m *QueryApplicantsResponse) GetPagination() query.PageResponse { + if m != nil { + return m.Pagination + } + return query.PageResponse{} +} + type QueryApplicantRequest struct { ApplicantId uint64 `protobuf:"varint,1,opt,name=applicant_id,json=applicantId,proto3" json:"applicant_id,omitempty"` } @@ -302,7 +398,7 @@ func (m *QueryApplicantRequest) Reset() { *m = QueryApplicantRequest{} } func (m *QueryApplicantRequest) String() string { return proto.CompactTextString(m) } func (*QueryApplicantRequest) ProtoMessage() {} func (*QueryApplicantRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{6} + return fileDescriptor_07e89fd14debe1c1, []int{8} } func (m *QueryApplicantRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -346,7 +442,7 @@ func (m *QueryApplicantResponse) Reset() { *m = QueryApplicantResponse{} func (m *QueryApplicantResponse) String() string { return proto.CompactTextString(m) } func (*QueryApplicantResponse) ProtoMessage() {} func (*QueryApplicantResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{7} + return fileDescriptor_07e89fd14debe1c1, []int{9} } func (m *QueryApplicantResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -390,7 +486,7 @@ func (m *QueryCreditClassesRequest) Reset() { *m = QueryCreditClassesReq func (m *QueryCreditClassesRequest) String() string { return proto.CompactTextString(m) } func (*QueryCreditClassesRequest) ProtoMessage() {} func (*QueryCreditClassesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{8} + return fileDescriptor_07e89fd14debe1c1, []int{10} } func (m *QueryCreditClassesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -435,7 +531,7 @@ func (m *QueryCreditClassesResponse) Reset() { *m = QueryCreditClassesRe func (m *QueryCreditClassesResponse) String() string { return proto.CompactTextString(m) } func (*QueryCreditClassesResponse) ProtoMessage() {} func (*QueryCreditClassesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{9} + return fileDescriptor_07e89fd14debe1c1, []int{11} } func (m *QueryCreditClassesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -486,7 +582,7 @@ func (m *QueryCreditClassRequest) Reset() { *m = QueryCreditClassRequest func (m *QueryCreditClassRequest) String() string { return proto.CompactTextString(m) } func (*QueryCreditClassRequest) ProtoMessage() {} func (*QueryCreditClassRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{10} + return fileDescriptor_07e89fd14debe1c1, []int{12} } func (m *QueryCreditClassRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -530,7 +626,7 @@ func (m *QueryCreditClassResponse) Reset() { *m = QueryCreditClassRespon func (m *QueryCreditClassResponse) String() string { return proto.CompactTextString(m) } func (*QueryCreditClassResponse) ProtoMessage() {} func (*QueryCreditClassResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{11} + return fileDescriptor_07e89fd14debe1c1, []int{13} } func (m *QueryCreditClassResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -566,6 +662,102 @@ func (m *QueryCreditClassResponse) GetCreditClass() CreditClass { return CreditClass{} } +type QueryProjectsRequest struct { + Pagination query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryProjectsRequest) Reset() { *m = QueryProjectsRequest{} } +func (m *QueryProjectsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProjectsRequest) ProtoMessage() {} +func (*QueryProjectsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{14} +} +func (m *QueryProjectsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProjectsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProjectsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryProjectsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProjectsRequest.Merge(m, src) +} +func (m *QueryProjectsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProjectsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProjectsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProjectsRequest proto.InternalMessageInfo + +func (m *QueryProjectsRequest) GetPagination() query.PageRequest { + if m != nil { + return m.Pagination + } + return query.PageRequest{} +} + +type QueryProjectsResponse struct { + Projects []Project `protobuf:"bytes,1,rep,name=projects,proto3" json:"projects"` + Pagination query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryProjectsResponse) Reset() { *m = QueryProjectsResponse{} } +func (m *QueryProjectsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProjectsResponse) ProtoMessage() {} +func (*QueryProjectsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{15} +} +func (m *QueryProjectsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProjectsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProjectsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryProjectsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProjectsResponse.Merge(m, src) +} +func (m *QueryProjectsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProjectsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProjectsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProjectsResponse proto.InternalMessageInfo + +func (m *QueryProjectsResponse) GetProjects() []Project { + if m != nil { + return m.Projects + } + return nil +} + +func (m *QueryProjectsResponse) GetPagination() query.PageResponse { + if m != nil { + return m.Pagination + } + return query.PageResponse{} +} + type QueryProjectRequest struct { ProjectId uint64 `protobuf:"varint,1,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` } @@ -574,7 +766,7 @@ func (m *QueryProjectRequest) Reset() { *m = QueryProjectRequest{} } func (m *QueryProjectRequest) String() string { return proto.CompactTextString(m) } func (*QueryProjectRequest) ProtoMessage() {} func (*QueryProjectRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{12} + return fileDescriptor_07e89fd14debe1c1, []int{16} } func (m *QueryProjectRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -618,7 +810,7 @@ func (m *QueryProjectResponse) Reset() { *m = QueryProjectResponse{} } func (m *QueryProjectResponse) String() string { return proto.CompactTextString(m) } func (*QueryProjectResponse) ProtoMessage() {} func (*QueryProjectResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{13} + return fileDescriptor_07e89fd14debe1c1, []int{17} } func (m *QueryProjectResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -662,7 +854,7 @@ func (m *QueryCreditCollectionRequest) Reset() { *m = QueryCreditCollect func (m *QueryCreditCollectionRequest) String() string { return proto.CompactTextString(m) } func (*QueryCreditCollectionRequest) ProtoMessage() {} func (*QueryCreditCollectionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{14} + return fileDescriptor_07e89fd14debe1c1, []int{18} } func (m *QueryCreditCollectionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -706,7 +898,7 @@ func (m *QueryCreditCollectionResponse) Reset() { *m = QueryCreditCollec func (m *QueryCreditCollectionResponse) String() string { return proto.CompactTextString(m) } func (*QueryCreditCollectionResponse) ProtoMessage() {} func (*QueryCreditCollectionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{15} + return fileDescriptor_07e89fd14debe1c1, []int{19} } func (m *QueryCreditCollectionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -742,6 +934,102 @@ func (m *QueryCreditCollectionResponse) GetCreditCollection() CreditCollection { return CreditCollection{} } +type QueryCreditBalancesRequest struct { + Pagination query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryCreditBalancesRequest) Reset() { *m = QueryCreditBalancesRequest{} } +func (m *QueryCreditBalancesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryCreditBalancesRequest) ProtoMessage() {} +func (*QueryCreditBalancesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{20} +} +func (m *QueryCreditBalancesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCreditBalancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCreditBalancesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryCreditBalancesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCreditBalancesRequest.Merge(m, src) +} +func (m *QueryCreditBalancesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryCreditBalancesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCreditBalancesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCreditBalancesRequest proto.InternalMessageInfo + +func (m *QueryCreditBalancesRequest) GetPagination() query.PageRequest { + if m != nil { + return m.Pagination + } + return query.PageRequest{} +} + +type QueryCreditBalancesResponse struct { + CreditBalances []CreditBalance `protobuf:"bytes,1,rep,name=credit_balances,json=creditBalances,proto3" json:"credit_balances"` + Pagination query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination"` +} + +func (m *QueryCreditBalancesResponse) Reset() { *m = QueryCreditBalancesResponse{} } +func (m *QueryCreditBalancesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryCreditBalancesResponse) ProtoMessage() {} +func (*QueryCreditBalancesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_07e89fd14debe1c1, []int{21} +} +func (m *QueryCreditBalancesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryCreditBalancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryCreditBalancesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryCreditBalancesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryCreditBalancesResponse.Merge(m, src) +} +func (m *QueryCreditBalancesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryCreditBalancesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryCreditBalancesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryCreditBalancesResponse proto.InternalMessageInfo + +func (m *QueryCreditBalancesResponse) GetCreditBalances() []CreditBalance { + if m != nil { + return m.CreditBalances + } + return nil +} + +func (m *QueryCreditBalancesResponse) GetPagination() query.PageResponse { + if m != nil { + return m.Pagination + } + return query.PageResponse{} +} + type QueryCreditBalanceRequest struct { Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` @@ -751,7 +1039,7 @@ func (m *QueryCreditBalanceRequest) Reset() { *m = QueryCreditBalanceReq func (m *QueryCreditBalanceRequest) String() string { return proto.CompactTextString(m) } func (*QueryCreditBalanceRequest) ProtoMessage() {} func (*QueryCreditBalanceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{16} + return fileDescriptor_07e89fd14debe1c1, []int{22} } func (m *QueryCreditBalanceRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -802,7 +1090,7 @@ func (m *QueryCreditBalanceResponse) Reset() { *m = QueryCreditBalanceRe func (m *QueryCreditBalanceResponse) String() string { return proto.CompactTextString(m) } func (*QueryCreditBalanceResponse) ProtoMessage() {} func (*QueryCreditBalanceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_07e89fd14debe1c1, []int{17} + return fileDescriptor_07e89fd14debe1c1, []int{23} } func (m *QueryCreditBalanceResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -845,16 +1133,22 @@ func init() { proto.RegisterType((*QueryIssuersResponse)(nil), "empowerchain.plasticcredit.QueryIssuersResponse") proto.RegisterType((*QueryIssuerRequest)(nil), "empowerchain.plasticcredit.QueryIssuerRequest") proto.RegisterType((*QueryIssuerResponse)(nil), "empowerchain.plasticcredit.QueryIssuerResponse") + proto.RegisterType((*QueryApplicantsRequest)(nil), "empowerchain.plasticcredit.QueryApplicantsRequest") + proto.RegisterType((*QueryApplicantsResponse)(nil), "empowerchain.plasticcredit.QueryApplicantsResponse") proto.RegisterType((*QueryApplicantRequest)(nil), "empowerchain.plasticcredit.QueryApplicantRequest") proto.RegisterType((*QueryApplicantResponse)(nil), "empowerchain.plasticcredit.QueryApplicantResponse") proto.RegisterType((*QueryCreditClassesRequest)(nil), "empowerchain.plasticcredit.QueryCreditClassesRequest") proto.RegisterType((*QueryCreditClassesResponse)(nil), "empowerchain.plasticcredit.QueryCreditClassesResponse") proto.RegisterType((*QueryCreditClassRequest)(nil), "empowerchain.plasticcredit.QueryCreditClassRequest") proto.RegisterType((*QueryCreditClassResponse)(nil), "empowerchain.plasticcredit.QueryCreditClassResponse") + proto.RegisterType((*QueryProjectsRequest)(nil), "empowerchain.plasticcredit.QueryProjectsRequest") + proto.RegisterType((*QueryProjectsResponse)(nil), "empowerchain.plasticcredit.QueryProjectsResponse") proto.RegisterType((*QueryProjectRequest)(nil), "empowerchain.plasticcredit.QueryProjectRequest") proto.RegisterType((*QueryProjectResponse)(nil), "empowerchain.plasticcredit.QueryProjectResponse") proto.RegisterType((*QueryCreditCollectionRequest)(nil), "empowerchain.plasticcredit.QueryCreditCollectionRequest") proto.RegisterType((*QueryCreditCollectionResponse)(nil), "empowerchain.plasticcredit.QueryCreditCollectionResponse") + proto.RegisterType((*QueryCreditBalancesRequest)(nil), "empowerchain.plasticcredit.QueryCreditBalancesRequest") + proto.RegisterType((*QueryCreditBalancesResponse)(nil), "empowerchain.plasticcredit.QueryCreditBalancesResponse") proto.RegisterType((*QueryCreditBalanceRequest)(nil), "empowerchain.plasticcredit.QueryCreditBalanceRequest") proto.RegisterType((*QueryCreditBalanceResponse)(nil), "empowerchain.plasticcredit.QueryCreditBalanceResponse") } @@ -864,70 +1158,80 @@ func init() { } var fileDescriptor_07e89fd14debe1c1 = []byte{ - // 1000 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x97, 0xcf, 0x6f, 0x1b, 0x45, - 0x14, 0xc7, 0x33, 0xa1, 0x8d, 0xf1, 0x4b, 0x83, 0xca, 0x10, 0x68, 0xba, 0xb4, 0xa6, 0x0c, 0xa2, - 0x05, 0x04, 0x3b, 0x75, 0x1a, 0xfa, 0x4b, 0xa8, 0xb4, 0x4e, 0xa1, 0x32, 0x02, 0x61, 0x0c, 0x15, - 0x12, 0x3d, 0x44, 0xe3, 0xf5, 0xc8, 0x5d, 0x64, 0xef, 0x6c, 0x3d, 0x9b, 0x96, 0xca, 0xb2, 0x84, - 0xf8, 0x0b, 0x90, 0xf8, 0x0f, 0x38, 0x20, 0x71, 0xe2, 0xc2, 0x19, 0xd4, 0x5b, 0x6f, 0x54, 0xaa, - 0x90, 0x38, 0x21, 0x94, 0xf0, 0x87, 0x20, 0xcf, 0xbc, 0xfd, 0xd9, 0xc4, 0x5e, 0x47, 0xf4, 0x64, - 0xfb, 0xed, 0x7c, 0xdf, 0xfb, 0xbc, 0xb7, 0x33, 0xf3, 0x95, 0xe1, 0xb4, 0x1c, 0x84, 0xea, 0x9e, - 0x1c, 0x7a, 0xb7, 0x85, 0x1f, 0xf0, 0xb0, 0x2f, 0x74, 0xe4, 0x7b, 0xde, 0x50, 0x76, 0xfd, 0x88, - 0xdf, 0xd9, 0x96, 0xc3, 0xfb, 0x6e, 0x38, 0x54, 0x91, 0xa2, 0x4e, 0x76, 0x9d, 0x9b, 0x5b, 0xe7, - 0xbc, 0xe5, 0x29, 0x3d, 0x50, 0x9a, 0x77, 0x84, 0x96, 0x56, 0xc4, 0xef, 0xd6, 0x3b, 0x32, 0x12, - 0x75, 0x1e, 0x8a, 0x9e, 0x1f, 0x88, 0xc8, 0x57, 0x81, 0xcd, 0xe3, 0x4c, 0xab, 0x17, 0xdd, 0x0f, - 0xa5, 0xc6, 0x75, 0xab, 0x3d, 0xd5, 0x53, 0xe6, 0x2b, 0x9f, 0x7c, 0xc3, 0xe8, 0x89, 0x9e, 0x52, - 0xbd, 0xbe, 0xe4, 0x22, 0xf4, 0xb9, 0x08, 0x02, 0x15, 0x99, 0xd4, 0xa8, 0x61, 0xab, 0x40, 0x3f, - 0x9b, 0x54, 0x6f, 0x89, 0xa1, 0x18, 0xe8, 0xb6, 0xbc, 0xb3, 0x2d, 0x75, 0xc4, 0xbe, 0x84, 0x17, - 0x72, 0x51, 0x1d, 0xaa, 0x40, 0x4b, 0x7a, 0x15, 0x96, 0x42, 0x13, 0x59, 0x23, 0xa7, 0xc8, 0x1b, - 0xcb, 0xeb, 0xcc, 0xdd, 0xbf, 0x43, 0xd7, 0x6a, 0x1b, 0x87, 0x1e, 0xfe, 0xfd, 0xca, 0x42, 0x1b, - 0x75, 0xcc, 0xc3, 0xc4, 0x4d, 0xad, 0xb7, 0xe5, 0x30, 0xae, 0x47, 0x3f, 0x06, 0x48, 0xbb, 0xc6, - 0xe4, 0xa7, 0x5d, 0x3b, 0x22, 0x77, 0x32, 0x22, 0xd7, 0xce, 0x15, 0x47, 0xe4, 0xb6, 0x44, 0x4f, - 0xa2, 0x16, 0x0b, 0x64, 0xf4, 0xec, 0x67, 0x02, 0xab, 0xf9, 0x2a, 0xc8, 0xdf, 0x80, 0x8a, 0x6f, - 0x43, 0x6b, 0xe4, 0xd4, 0x33, 0xb3, 0x1a, 0xb0, 0x6a, 0xcc, 0x1f, 0x0b, 0xe9, 0x27, 0x39, 0xd4, - 0x45, 0x83, 0x7a, 0x66, 0x26, 0xaa, 0x05, 0xd8, 0x83, 0xb5, 0x8e, 0xf3, 0xb7, 0xc5, 0xe2, 0x79, - 0xbc, 0x0c, 0x55, 0x5b, 0x6f, 0xcb, 0xef, 0x9a, 0x71, 0x1c, 0x6a, 0x3f, 0x6b, 0x03, 0xcd, 0x6e, - 0xf2, 0x72, 0x62, 0x49, 0xfa, 0x72, 0xec, 0x92, 0x32, 0x2f, 0x27, 0xd7, 0x1b, 0xea, 0xd8, 0x65, - 0x78, 0xd1, 0x24, 0xbe, 0x16, 0x86, 0x7d, 0xdf, 0x13, 0x41, 0x14, 0xe3, 0xbc, 0x0a, 0x47, 0x44, - 0x1c, 0x4b, 0x89, 0x96, 0x93, 0x58, 0xb3, 0xcb, 0x3c, 0x78, 0xa9, 0xa8, 0x45, 0xae, 0x26, 0x54, - 0x93, 0x85, 0x88, 0xf6, 0xfa, 0x34, 0xb4, 0x24, 0x03, 0xd2, 0xa5, 0x6a, 0xe6, 0xc3, 0x71, 0x53, - 0x64, 0xd3, 0xac, 0xdc, 0xec, 0x0b, 0xad, 0xe5, 0x53, 0xda, 0x43, 0x0f, 0x08, 0x38, 0x7b, 0xd5, - 0xc2, 0xa6, 0xbe, 0x80, 0xe7, 0x2c, 0xee, 0x96, 0x67, 0x9f, 0xe0, 0x86, 0x3a, 0x33, 0xad, 0xb3, - 0x4c, 0x2a, 0xac, 0xb8, 0xe2, 0x65, 0xb3, 0xff, 0xdf, 0x7b, 0xeb, 0x26, 0x1c, 0x2b, 0xb6, 0x10, - 0x0f, 0xeb, 0x32, 0x1c, 0xcf, 0xf2, 0x6f, 0x89, 0x4e, 0x67, 0x28, 0xef, 0xfa, 0xe9, 0xec, 0xaa, - 0xed, 0x63, 0x19, 0xb6, 0x6b, 0x99, 0xc7, 0xac, 0x0f, 0x6b, 0x4f, 0xa6, 0xc5, 0xb9, 0xb4, 0xe0, - 0x48, 0x36, 0x2f, 0xbe, 0x86, 0x39, 0xa7, 0xb2, 0x9c, 0xa9, 0xcc, 0x36, 0xe2, 0xab, 0x68, 0xa8, - 0xbe, 0x96, 0x5e, 0xb2, 0x25, 0x4f, 0x02, 0x84, 0x36, 0x92, 0x6e, 0xc8, 0x2a, 0x46, 0x9a, 0x5d, - 0x76, 0x0b, 0x6f, 0x80, 0x44, 0x85, 0x7c, 0x9b, 0x50, 0xc1, 0x45, 0x88, 0xf6, 0xda, 0xd4, 0x2b, - 0xcc, 0x2e, 0x8d, 0xaf, 0x00, 0x54, 0xb2, 0x0d, 0x38, 0x91, 0x1d, 0x80, 0xea, 0xf7, 0xa5, 0x37, - 0x99, 0x4c, 0xcc, 0xb6, 0x0a, 0x87, 0xbb, 0x32, 0x50, 0x03, 0x1c, 0xa4, 0xfd, 0xc1, 0xbe, 0x25, - 0x70, 0x72, 0x1f, 0x19, 0xc2, 0x6d, 0xc1, 0xf3, 0xf1, 0xf0, 0x92, 0x87, 0x88, 0xf9, 0x76, 0x89, - 0x09, 0x26, 0x1a, 0xe4, 0x3d, 0xea, 0x15, 0xe2, 0xec, 0x46, 0xee, 0xfc, 0x34, 0x44, 0x5f, 0x04, - 0x9e, 0xcc, 0x50, 0xab, 0x7b, 0x01, 0x5e, 0x1f, 0xd5, 0xb6, 0xfd, 0x91, 0xf6, 0xb2, 0x98, 0xed, - 0xa5, 0x97, 0x3b, 0x1c, 0x49, 0xa2, 0xe4, 0xc4, 0x57, 0x3a, 0x36, 0x84, 0xf4, 0x6f, 0xce, 0xa6, - 0xc7, 0x1c, 0xf1, 0xa8, 0x51, 0xbf, 0xfe, 0x60, 0x05, 0x0e, 0x9b, 0x4a, 0xf4, 0x47, 0x02, 0x4b, - 0xd6, 0x52, 0xa8, 0x3b, 0x2d, 0xdd, 0x93, 0x6e, 0xe6, 0xf0, 0xd2, 0xeb, 0x6d, 0x03, 0xec, 0xc2, - 0x77, 0x8f, 0xff, 0xfd, 0x61, 0xb1, 0x4e, 0x39, 0xcf, 0x39, 0xef, 0x14, 0x1b, 0xb6, 0xf6, 0x46, - 0x7f, 0x22, 0x50, 0x41, 0xd3, 0xa1, 0xb3, 0xab, 0xe6, 0x4d, 0xd0, 0x39, 0x5b, 0x5e, 0x80, 0x9c, - 0x17, 0x0d, 0xe7, 0x3a, 0x3d, 0x5b, 0x9a, 0x33, 0x76, 0xb1, 0x5f, 0x08, 0x2c, 0xd9, 0x6c, 0x25, - 0xa6, 0x99, 0xf3, 0x26, 0x87, 0x97, 0x5e, 0x8f, 0x94, 0xd7, 0x0d, 0xe5, 0x15, 0xfa, 0xde, 0xbc, - 0x94, 0x7c, 0x94, 0x98, 0xe0, 0x98, 0xfe, 0x46, 0xa0, 0x9a, 0x58, 0x03, 0xad, 0xcf, 0x84, 0x28, - 0x9a, 0x98, 0xb3, 0x3e, 0x8f, 0x04, 0xd1, 0x3f, 0x32, 0xe8, 0xd7, 0x69, 0xa3, 0x34, 0x7a, 0x62, - 0x56, 0x9a, 0x8f, 0xb2, 0x9e, 0x39, 0xa6, 0xbf, 0x13, 0x58, 0xc9, 0x99, 0x09, 0x7d, 0x77, 0x26, - 0xd1, 0x5e, 0x46, 0xe7, 0x9c, 0x9f, 0x57, 0x86, 0xcd, 0xbc, 0x6f, 0x9a, 0xb9, 0x44, 0x2f, 0x94, - 0x6e, 0xc6, 0x7e, 0xbc, 0x83, 0x16, 0x47, 0xff, 0x24, 0xb0, 0x9c, 0x49, 0x4d, 0xcf, 0xcd, 0x03, - 0x12, 0xd3, 0x6f, 0xcc, 0x27, 0x42, 0xf6, 0x5b, 0x86, 0xfd, 0x26, 0xfd, 0xfc, 0x80, 0xec, 0x7c, - 0xb4, 0xaf, 0xdd, 0x8d, 0xe9, 0xaf, 0x04, 0x2a, 0x78, 0xd5, 0x97, 0x38, 0xb5, 0x79, 0x23, 0x2a, - 0x71, 0x6a, 0x0b, 0x1e, 0xc4, 0x3e, 0x34, 0xbd, 0x5c, 0xa5, 0x57, 0xca, 0xdf, 0x2e, 0x36, 0x83, - 0xe6, 0xa3, 0xd4, 0xf3, 0xc6, 0xf4, 0x31, 0x81, 0xa3, 0xc5, 0xab, 0x9f, 0x5e, 0x2c, 0x3b, 0xde, - 0xa2, 0x6b, 0x39, 0x97, 0x0e, 0xa0, 0x3c, 0xf0, 0x31, 0xb1, 0x1f, 0xa9, 0xcd, 0x69, 0x3e, 0x32, - 0xce, 0x32, 0xa6, 0x7f, 0x24, 0xc7, 0x04, 0x2d, 0xa1, 0xf4, 0x31, 0xc9, 0xfb, 0x59, 0xe9, 0x63, - 0x52, 0x70, 0x2f, 0xf6, 0xa9, 0x69, 0xa6, 0x49, 0x6f, 0xcc, 0xd9, 0x0c, 0x5a, 0x96, 0xe6, 0x23, - 0xe3, 0x9c, 0xe3, 0xb8, 0xa3, 0x46, 0xeb, 0xe1, 0x4e, 0x8d, 0x3c, 0xda, 0xa9, 0x91, 0x7f, 0x76, - 0x6a, 0xe4, 0xfb, 0xdd, 0xda, 0xc2, 0xa3, 0xdd, 0xda, 0xc2, 0x5f, 0xbb, 0xb5, 0x85, 0xaf, 0xce, - 0xf7, 0xfc, 0xe8, 0xf6, 0x76, 0xc7, 0xf5, 0xd4, 0x80, 0x7f, 0x60, 0xf3, 0xb7, 0x6c, 0xe6, 0x7c, - 0xb9, 0x6f, 0xf2, 0x05, 0x3b, 0x4b, 0xe6, 0xbf, 0xdb, 0xb9, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, - 0x36, 0x4f, 0x19, 0x57, 0x89, 0x0e, 0x00, 0x00, + // 1166 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xdf, 0x6f, 0xdb, 0x54, + 0x14, 0xee, 0x2d, 0x5b, 0xd3, 0x9c, 0x6e, 0x63, 0xbb, 0x14, 0xd6, 0x79, 0x5b, 0x18, 0x46, 0x6c, + 0x80, 0xc0, 0xb7, 0x49, 0xba, 0x76, 0x1d, 0x68, 0x6c, 0xe9, 0xc6, 0x14, 0x7e, 0x88, 0x10, 0x98, + 0x40, 0xec, 0xa1, 0x72, 0x1c, 0x93, 0x79, 0x4a, 0x6c, 0x2f, 0x76, 0x37, 0xa6, 0x28, 0x12, 0xe2, + 0x2f, 0x40, 0xe2, 0x3f, 0xe0, 0x01, 0x09, 0x24, 0x84, 0x84, 0xe0, 0x15, 0x04, 0x0f, 0x68, 0x6f, + 0x4c, 0x9a, 0x90, 0x78, 0x42, 0xa8, 0xe5, 0x81, 0x3f, 0x03, 0xf5, 0xde, 0x73, 0x6d, 0xdf, 0x34, + 0x4d, 0xec, 0xd0, 0x3e, 0xb5, 0xbd, 0xbe, 0xdf, 0xf9, 0xbe, 0xef, 0x9c, 0xeb, 0xeb, 0x4f, 0x85, + 0xb3, 0x76, 0xc7, 0xf7, 0xee, 0xd9, 0x5d, 0xeb, 0x96, 0xe9, 0xb8, 0xcc, 0x6f, 0x9b, 0x41, 0xe8, + 0x58, 0x56, 0xd7, 0x6e, 0x3a, 0x21, 0xbb, 0xb3, 0x61, 0x77, 0xef, 0x1b, 0x7e, 0xd7, 0x0b, 0x3d, + 0xaa, 0x25, 0xf7, 0x19, 0xca, 0x3e, 0xed, 0x45, 0xcb, 0x0b, 0x3a, 0x5e, 0xc0, 0x1a, 0x66, 0x60, + 0x0b, 0x10, 0xbb, 0x5b, 0x6c, 0xd8, 0xa1, 0x59, 0x64, 0xbe, 0xd9, 0x72, 0x5c, 0x33, 0x74, 0x3c, + 0x57, 0xd4, 0xd1, 0x46, 0xf1, 0x85, 0xf7, 0x7d, 0x3b, 0xc0, 0x7d, 0xf3, 0x2d, 0xaf, 0xe5, 0xf1, + 0x5f, 0xd9, 0xf6, 0x6f, 0xb8, 0x7a, 0xaa, 0xe5, 0x79, 0xad, 0xb6, 0xcd, 0x4c, 0xdf, 0x61, 0xa6, + 0xeb, 0x7a, 0x21, 0x2f, 0x8d, 0x18, 0x7d, 0x1e, 0xe8, 0xbb, 0xdb, 0xec, 0x35, 0xb3, 0x6b, 0x76, + 0x82, 0xba, 0x7d, 0x67, 0xc3, 0x0e, 0x42, 0xfd, 0x03, 0x78, 0x42, 0x59, 0x0d, 0x7c, 0xcf, 0x0d, + 0x6c, 0x7a, 0x19, 0x66, 0x7c, 0xbe, 0xb2, 0x40, 0xce, 0x90, 0xe7, 0xe7, 0x4a, 0xba, 0xb1, 0xbb, + 0x43, 0x43, 0x60, 0x2b, 0x07, 0x1e, 0xfc, 0xf5, 0xf4, 0x54, 0x1d, 0x71, 0xba, 0x85, 0x85, 0xab, + 0x41, 0xb0, 0x61, 0x77, 0x25, 0x1f, 0x7d, 0x0b, 0x20, 0x76, 0x8d, 0xc5, 0xcf, 0x1a, 0xa2, 0x45, + 0xc6, 0x76, 0x8b, 0x0c, 0xd1, 0x57, 0x6c, 0x91, 0x51, 0x33, 0x5b, 0x36, 0x62, 0x91, 0x20, 0x81, + 0xd7, 0xbf, 0x26, 0x30, 0xaf, 0xb2, 0xa0, 0xfe, 0x0a, 0xe4, 0x1c, 0xb1, 0xb4, 0x40, 0xce, 0x3c, + 0x36, 0xce, 0x80, 0x40, 0x63, 0x7d, 0x09, 0xa4, 0x6f, 0x2b, 0x52, 0xa7, 0xb9, 0xd4, 0x73, 0x63, + 0xa5, 0x0a, 0x01, 0x43, 0xb4, 0x16, 0xb1, 0xff, 0x82, 0x4c, 0xf6, 0xe3, 0x24, 0xe4, 0x05, 0xdf, + 0xba, 0xd3, 0xe4, 0xed, 0x38, 0x50, 0x9f, 0x15, 0x0b, 0xd5, 0x66, 0x34, 0x1c, 0x09, 0x89, 0x87, + 0x23, 0xb6, 0xa4, 0x19, 0x8e, 0xe2, 0x0d, 0x71, 0xfa, 0xc7, 0xf0, 0x14, 0x2f, 0x7c, 0xc5, 0xf7, + 0xdb, 0x8e, 0x65, 0xba, 0xe1, 0x3e, 0xcd, 0xe7, 0x47, 0x02, 0xc7, 0x77, 0x10, 0xa1, 0x8b, 0x37, + 0x01, 0xcc, 0x68, 0x15, 0xa7, 0xf4, 0xdc, 0x28, 0x27, 0x51, 0x0d, 0x49, 0x14, 0xc3, 0xf7, 0x7a, + 0x56, 0x17, 0xe1, 0x49, 0x55, 0xb6, 0x6c, 0xcf, 0x33, 0x70, 0x28, 0x62, 0x8d, 0x27, 0x36, 0x17, + 0xad, 0x55, 0x9b, 0xba, 0x35, 0xd8, 0xdb, 0xc8, 0x71, 0x15, 0xf2, 0xd1, 0x46, 0x6c, 0x6d, 0x26, + 0xc3, 0x31, 0x5a, 0x77, 0xe0, 0x04, 0x27, 0x59, 0xe3, 0x3b, 0xd7, 0xda, 0x66, 0x10, 0xd8, 0xfb, + 0x34, 0xc3, 0x5f, 0x08, 0x68, 0xc3, 0xb8, 0xd0, 0xd4, 0xfb, 0x70, 0x44, 0xc8, 0x5d, 0xb7, 0xc4, + 0x13, 0x1c, 0xe5, 0xb9, 0x51, 0xce, 0x12, 0xa5, 0x90, 0xf1, 0xb0, 0x95, 0xac, 0xbe, 0xd7, 0xf3, + 0xbc, 0x81, 0xc7, 0x30, 0xc1, 0x2b, 0x9b, 0x75, 0x11, 0x4e, 0x24, 0xf5, 0xaf, 0x9b, 0x8d, 0x46, + 0xd7, 0xbe, 0xeb, 0xc4, 0xbd, 0xcb, 0xd7, 0x8f, 0x27, 0xb4, 0x5d, 0x49, 0x3c, 0xd6, 0xdb, 0xb0, + 0xb0, 0xb3, 0x2c, 0xf6, 0xa5, 0x06, 0x87, 0x92, 0x75, 0x71, 0x0c, 0x19, 0xbb, 0x32, 0x97, 0x60, + 0xd6, 0x9b, 0x78, 0xd7, 0xd5, 0xba, 0xde, 0x6d, 0xdb, 0xda, 0xaf, 0x57, 0xf6, 0x5b, 0x82, 0x67, + 0x3f, 0xa6, 0x41, 0x47, 0xd7, 0x60, 0xd6, 0xc7, 0x35, 0x9c, 0xf1, 0xb3, 0x23, 0xbf, 0x0a, 0x62, + 0x2f, 0x52, 0x44, 0xd0, 0xbd, 0x1e, 0xed, 0x92, 0xfc, 0x80, 0x89, 0xfa, 0xb2, 0x29, 0xa7, 0x01, + 0x90, 0x31, 0x7e, 0x4d, 0xf3, 0xb8, 0x52, 0x6d, 0xea, 0x37, 0xd5, 0x5e, 0x46, 0x1e, 0xd7, 0x20, + 0x87, 0x9b, 0xb0, 0x91, 0x19, 0x2c, 0x4a, 0xa4, 0xbe, 0x04, 0xa7, 0x92, 0xc7, 0xc2, 0x6b, 0xb7, + 0x6d, 0x6b, 0x5b, 0xab, 0xd4, 0x36, 0x0f, 0x07, 0x9b, 0xb6, 0xeb, 0x75, 0xf0, 0x78, 0x89, 0x3f, + 0xf4, 0x4f, 0x09, 0x9c, 0xde, 0x05, 0x86, 0xe2, 0xd6, 0xe1, 0x98, 0x3c, 0x52, 0xd1, 0x43, 0x94, + 0xf9, 0x52, 0x8a, 0x73, 0x15, 0x61, 0x50, 0xef, 0x51, 0x6b, 0x60, 0x5d, 0xbf, 0xad, 0xbc, 0xe9, + 0x15, 0xb3, 0x6d, 0xba, 0xd6, 0x7e, 0x5d, 0x2b, 0xbf, 0x11, 0x38, 0x39, 0x94, 0x0c, 0xcd, 0x7e, + 0x08, 0x8f, 0xa3, 0xd9, 0x06, 0x3e, 0xc2, 0x43, 0xf7, 0xc2, 0x78, 0xab, 0x58, 0x0c, 0x59, 0xf1, + 0x7e, 0x92, 0x0c, 0x7b, 0x7d, 0x00, 0xaf, 0x2b, 0x57, 0x31, 0xb2, 0x24, 0x46, 0xed, 0xdd, 0x73, + 0xf1, 0x4b, 0x9d, 0xaf, 0x8b, 0x3f, 0xe2, 0x03, 0x30, 0x9d, 0x3c, 0x00, 0xad, 0x61, 0xdd, 0x4f, + 0x7c, 0x3c, 0x72, 0xd8, 0x08, 0x6c, 0x7d, 0xe6, 0x3e, 0x48, 0x7c, 0xe9, 0xdf, 0x63, 0x70, 0x90, + 0x33, 0xd1, 0x2f, 0x09, 0xcc, 0x88, 0xf4, 0x46, 0x8d, 0x51, 0xe5, 0x76, 0x06, 0x47, 0x8d, 0xa5, + 0xde, 0x2f, 0x0c, 0xe8, 0x2b, 0x9f, 0x3d, 0xfa, 0xe7, 0x8b, 0xe9, 0x22, 0x65, 0x4c, 0x09, 0xb9, + 0x23, 0x12, 0xaf, 0x48, 0x92, 0xf4, 0x2b, 0x02, 0x39, 0xcc, 0x77, 0x74, 0x3c, 0xab, 0x9a, 0x37, + 0xb5, 0xc5, 0xf4, 0x00, 0xd4, 0x79, 0x81, 0xeb, 0x2c, 0xd1, 0xc5, 0xd4, 0x3a, 0x65, 0x60, 0xfc, + 0x8e, 0xc0, 0x8c, 0xa8, 0x96, 0xa2, 0x9b, 0x4a, 0x0c, 0xd4, 0x58, 0xea, 0xfd, 0xa8, 0xf2, 0x2a, + 0x57, 0x79, 0x89, 0xbe, 0x9a, 0x55, 0x25, 0xeb, 0x45, 0x79, 0xb3, 0x4f, 0xbf, 0x27, 0x00, 0x71, + 0x34, 0xa3, 0xa5, 0xb1, 0x2a, 0x76, 0x04, 0x46, 0xad, 0x9c, 0x09, 0x83, 0xea, 0x5f, 0xe1, 0xea, + 0xcf, 0xd3, 0x72, 0x6a, 0xf5, 0x89, 0xac, 0xf7, 0x13, 0x81, 0x7c, 0x54, 0x93, 0x16, 0xd3, 0xf3, + 0x4b, 0xc9, 0xa5, 0x2c, 0x10, 0x54, 0xfc, 0x06, 0x57, 0x7c, 0x95, 0x56, 0x26, 0x50, 0xcc, 0x7a, + 0xc9, 0xcc, 0xd8, 0xa7, 0x3f, 0x13, 0x38, 0xac, 0x84, 0x29, 0x7a, 0x7e, 0xac, 0xa2, 0x61, 0x41, + 0x4f, 0x5b, 0xce, 0x0a, 0x43, 0x33, 0xaf, 0x71, 0x33, 0xab, 0x74, 0x25, 0xb5, 0x19, 0xf1, 0xe3, + 0x65, 0x8c, 0x78, 0xf4, 0x0f, 0x02, 0x73, 0x89, 0xd2, 0xb4, 0x9c, 0x45, 0x88, 0x54, 0xbf, 0x94, + 0x0d, 0x84, 0xda, 0x6f, 0x72, 0xed, 0x37, 0xe8, 0x7b, 0x13, 0x6a, 0x67, 0xbd, 0x5d, 0xe3, 0x5e, + 0x9f, 0x7e, 0x43, 0x60, 0x56, 0xe6, 0x1e, 0x3a, 0xfe, 0xea, 0x18, 0x48, 0x62, 0x5a, 0x31, 0x03, + 0x02, 0xed, 0xac, 0x72, 0x3b, 0x65, 0x5a, 0x4c, 0x7f, 0x2b, 0x4a, 0x7d, 0x3f, 0x10, 0xc8, 0x61, + 0xbd, 0x14, 0xf7, 0xa2, 0x9a, 0x8f, 0xb4, 0xc5, 0xf4, 0x00, 0x54, 0xfa, 0x3a, 0x57, 0x7a, 0x99, + 0x5e, 0xca, 0xac, 0x94, 0xf5, 0xe2, 0x28, 0xd6, 0xa7, 0x8f, 0x08, 0x1c, 0x1d, 0x4c, 0x24, 0xf4, + 0x42, 0xda, 0xb3, 0x30, 0x18, 0xa6, 0xb4, 0xd5, 0x09, 0x90, 0x13, 0xbf, 0xd3, 0xe2, 0x47, 0x9c, + 0xbe, 0x02, 0xd6, 0xe3, 0xdf, 0xee, 0x3e, 0xfd, 0x95, 0xc0, 0x11, 0x35, 0xc9, 0xd0, 0xb4, 0x6f, + 0xe7, 0x40, 0xce, 0xd2, 0x56, 0x32, 0xe3, 0xfe, 0xe7, 0x6b, 0x2d, 0x03, 0x16, 0xfd, 0x3d, 0xba, + 0x98, 0xb0, 0x76, 0xea, 0x8b, 0x49, 0x8d, 0x3d, 0xda, 0x72, 0x56, 0x18, 0x3a, 0x78, 0x87, 0x3b, + 0xa8, 0xd2, 0xeb, 0x13, 0x3a, 0x60, 0x3d, 0x1e, 0xb0, 0xfa, 0x72, 0x2c, 0x95, 0xda, 0x83, 0xcd, + 0x02, 0x79, 0xb8, 0x59, 0x20, 0x7f, 0x6f, 0x16, 0xc8, 0xe7, 0x5b, 0x85, 0xa9, 0x87, 0x5b, 0x85, + 0xa9, 0x3f, 0xb7, 0x0a, 0x53, 0x1f, 0x2d, 0xb7, 0x9c, 0xf0, 0xd6, 0x46, 0xc3, 0xb0, 0xbc, 0x0e, + 0xbb, 0x26, 0xea, 0xd7, 0x44, 0x65, 0x95, 0xee, 0x13, 0x95, 0xb0, 0x31, 0xc3, 0xff, 0x9b, 0x56, + 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x14, 0xd2, 0x72, 0x1b, 0x14, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -945,11 +1249,14 @@ type QueryClient interface { Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) Issuers(ctx context.Context, in *QueryIssuersRequest, opts ...grpc.CallOption) (*QueryIssuersResponse, error) Issuer(ctx context.Context, in *QueryIssuerRequest, opts ...grpc.CallOption) (*QueryIssuerResponse, error) + Applicants(ctx context.Context, in *QueryApplicantsRequest, opts ...grpc.CallOption) (*QueryApplicantsResponse, error) Applicant(ctx context.Context, in *QueryApplicantRequest, opts ...grpc.CallOption) (*QueryApplicantResponse, error) CreditClasses(ctx context.Context, in *QueryCreditClassesRequest, opts ...grpc.CallOption) (*QueryCreditClassesResponse, error) CreditClass(ctx context.Context, in *QueryCreditClassRequest, opts ...grpc.CallOption) (*QueryCreditClassResponse, error) + Projects(ctx context.Context, in *QueryProjectsRequest, opts ...grpc.CallOption) (*QueryProjectsResponse, error) Project(ctx context.Context, in *QueryProjectRequest, opts ...grpc.CallOption) (*QueryProjectResponse, error) CreditCollection(ctx context.Context, in *QueryCreditCollectionRequest, opts ...grpc.CallOption) (*QueryCreditCollectionResponse, error) + CreditBalances(ctx context.Context, in *QueryCreditBalancesRequest, opts ...grpc.CallOption) (*QueryCreditBalancesResponse, error) CreditBalance(ctx context.Context, in *QueryCreditBalanceRequest, opts ...grpc.CallOption) (*QueryCreditBalanceResponse, error) } @@ -988,6 +1295,15 @@ func (c *queryClient) Issuer(ctx context.Context, in *QueryIssuerRequest, opts . return out, nil } +func (c *queryClient) Applicants(ctx context.Context, in *QueryApplicantsRequest, opts ...grpc.CallOption) (*QueryApplicantsResponse, error) { + out := new(QueryApplicantsResponse) + err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/Applicants", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Applicant(ctx context.Context, in *QueryApplicantRequest, opts ...grpc.CallOption) (*QueryApplicantResponse, error) { out := new(QueryApplicantResponse) err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/Applicant", in, out, opts...) @@ -1015,6 +1331,15 @@ func (c *queryClient) CreditClass(ctx context.Context, in *QueryCreditClassReque return out, nil } +func (c *queryClient) Projects(ctx context.Context, in *QueryProjectsRequest, opts ...grpc.CallOption) (*QueryProjectsResponse, error) { + out := new(QueryProjectsResponse) + err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/Projects", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Project(ctx context.Context, in *QueryProjectRequest, opts ...grpc.CallOption) (*QueryProjectResponse, error) { out := new(QueryProjectResponse) err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/Project", in, out, opts...) @@ -1033,6 +1358,15 @@ func (c *queryClient) CreditCollection(ctx context.Context, in *QueryCreditColle return out, nil } +func (c *queryClient) CreditBalances(ctx context.Context, in *QueryCreditBalancesRequest, opts ...grpc.CallOption) (*QueryCreditBalancesResponse, error) { + out := new(QueryCreditBalancesResponse) + err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/CreditBalances", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) CreditBalance(ctx context.Context, in *QueryCreditBalanceRequest, opts ...grpc.CallOption) (*QueryCreditBalanceResponse, error) { out := new(QueryCreditBalanceResponse) err := c.cc.Invoke(ctx, "/empowerchain.plasticcredit.Query/CreditBalance", in, out, opts...) @@ -1047,11 +1381,14 @@ type QueryServer interface { Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) Issuers(context.Context, *QueryIssuersRequest) (*QueryIssuersResponse, error) Issuer(context.Context, *QueryIssuerRequest) (*QueryIssuerResponse, error) + Applicants(context.Context, *QueryApplicantsRequest) (*QueryApplicantsResponse, error) Applicant(context.Context, *QueryApplicantRequest) (*QueryApplicantResponse, error) CreditClasses(context.Context, *QueryCreditClassesRequest) (*QueryCreditClassesResponse, error) CreditClass(context.Context, *QueryCreditClassRequest) (*QueryCreditClassResponse, error) + Projects(context.Context, *QueryProjectsRequest) (*QueryProjectsResponse, error) Project(context.Context, *QueryProjectRequest) (*QueryProjectResponse, error) CreditCollection(context.Context, *QueryCreditCollectionRequest) (*QueryCreditCollectionResponse, error) + CreditBalances(context.Context, *QueryCreditBalancesRequest) (*QueryCreditBalancesResponse, error) CreditBalance(context.Context, *QueryCreditBalanceRequest) (*QueryCreditBalanceResponse, error) } @@ -1068,6 +1405,9 @@ func (*UnimplementedQueryServer) Issuers(ctx context.Context, req *QueryIssuersR func (*UnimplementedQueryServer) Issuer(ctx context.Context, req *QueryIssuerRequest) (*QueryIssuerResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Issuer not implemented") } +func (*UnimplementedQueryServer) Applicants(ctx context.Context, req *QueryApplicantsRequest) (*QueryApplicantsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Applicants not implemented") +} func (*UnimplementedQueryServer) Applicant(ctx context.Context, req *QueryApplicantRequest) (*QueryApplicantResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Applicant not implemented") } @@ -1077,12 +1417,18 @@ func (*UnimplementedQueryServer) CreditClasses(ctx context.Context, req *QueryCr func (*UnimplementedQueryServer) CreditClass(ctx context.Context, req *QueryCreditClassRequest) (*QueryCreditClassResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreditClass not implemented") } +func (*UnimplementedQueryServer) Projects(ctx context.Context, req *QueryProjectsRequest) (*QueryProjectsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Projects not implemented") +} func (*UnimplementedQueryServer) Project(ctx context.Context, req *QueryProjectRequest) (*QueryProjectResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Project not implemented") } func (*UnimplementedQueryServer) CreditCollection(ctx context.Context, req *QueryCreditCollectionRequest) (*QueryCreditCollectionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreditCollection not implemented") } +func (*UnimplementedQueryServer) CreditBalances(ctx context.Context, req *QueryCreditBalancesRequest) (*QueryCreditBalancesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreditBalances not implemented") +} func (*UnimplementedQueryServer) CreditBalance(ctx context.Context, req *QueryCreditBalanceRequest) (*QueryCreditBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreditBalance not implemented") } @@ -1145,6 +1491,24 @@ func _Query_Issuer_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_Applicants_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryApplicantsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Applicants(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/empowerchain.plasticcredit.Query/Applicants", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Applicants(ctx, req.(*QueryApplicantsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Applicant_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryApplicantRequest) if err := dec(in); err != nil { @@ -1199,6 +1563,24 @@ func _Query_CreditClass_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Query_Projects_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProjectsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Projects(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/empowerchain.plasticcredit.Query/Projects", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Projects(ctx, req.(*QueryProjectsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Project_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryProjectRequest) if err := dec(in); err != nil { @@ -1235,13 +1617,31 @@ func _Query_CreditCollection_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } -func _Query_CreditBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryCreditBalanceRequest) +func _Query_CreditBalances_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCreditBalancesRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(QueryServer).CreditBalance(ctx, in) + return srv.(QueryServer).CreditBalances(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/empowerchain.plasticcredit.Query/CreditBalances", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).CreditBalances(ctx, req.(*QueryCreditBalancesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_CreditBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryCreditBalanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).CreditBalance(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, @@ -1269,6 +1669,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Issuer", Handler: _Query_Issuer_Handler, }, + { + MethodName: "Applicants", + Handler: _Query_Applicants_Handler, + }, { MethodName: "Applicant", Handler: _Query_Applicant_Handler, @@ -1281,6 +1685,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "CreditClass", Handler: _Query_CreditClass_Handler, }, + { + MethodName: "Projects", + Handler: _Query_Projects_Handler, + }, { MethodName: "Project", Handler: _Query_Project_Handler, @@ -1289,6 +1697,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "CreditCollection", Handler: _Query_CreditCollection_Handler, }, + { + MethodName: "CreditBalances", + Handler: _Query_CreditBalances_Handler, + }, { MethodName: "CreditBalance", Handler: _Query_CreditBalance_Handler, @@ -1495,6 +1907,86 @@ func (m *QueryIssuerResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryApplicantsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryApplicantsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryApplicantsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryApplicantsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryApplicantsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryApplicantsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Applicants) > 0 { + for iNdEx := len(m.Applicants) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Applicants[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *QueryApplicantRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1699,6 +2191,86 @@ func (m *QueryCreditClassResponse) MarshalToSizedBuffer(dAtA []byte) (int, error return len(dAtA) - i, nil } +func (m *QueryProjectsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryProjectsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProjectsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryProjectsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryProjectsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProjectsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Projects) > 0 { + for iNdEx := len(m.Projects) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Projects[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *QueryProjectRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1823,6 +2395,86 @@ func (m *QueryCreditCollectionResponse) MarshalToSizedBuffer(dAtA []byte) (int, return len(dAtA) - i, nil } +func (m *QueryCreditBalancesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryCreditBalancesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCreditBalancesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *QueryCreditBalancesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryCreditBalancesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryCreditBalancesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.CreditBalances) > 0 { + for iNdEx := len(m.CreditBalances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.CreditBalances[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *QueryCreditBalanceRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -1975,41 +2627,69 @@ func (m *QueryIssuerResponse) Size() (n int) { return n } -func (m *QueryApplicantRequest) Size() (n int) { +func (m *QueryApplicantsRequest) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.ApplicantId != 0 { - n += 1 + sovQuery(uint64(m.ApplicantId)) - } + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) return n } -func (m *QueryApplicantResponse) Size() (n int) { +func (m *QueryApplicantsResponse) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.Applicant.Size() + if len(m.Applicants) > 0 { + for _, e := range m.Applicants { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = m.Pagination.Size() n += 1 + l + sovQuery(uint64(l)) return n } -func (m *QueryCreditClassesRequest) Size() (n int) { +func (m *QueryApplicantRequest) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) + if m.ApplicantId != 0 { + n += 1 + sovQuery(uint64(m.ApplicantId)) + } return n } -func (m *QueryCreditClassesResponse) Size() (n int) { +func (m *QueryApplicantResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Applicant.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryCreditClassesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryCreditClassesResponse) Size() (n int) { if m == nil { return 0 } @@ -2050,6 +2730,34 @@ func (m *QueryCreditClassResponse) Size() (n int) { return n } +func (m *QueryProjectsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryProjectsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Projects) > 0 { + for _, e := range m.Projects { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func (m *QueryProjectRequest) Size() (n int) { if m == nil { return 0 @@ -2097,6 +2805,34 @@ func (m *QueryCreditCollectionResponse) Size() (n int) { return n } +func (m *QueryCreditBalancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *QueryCreditBalancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.CreditBalances) > 0 { + for _, e := range m.CreditBalances { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func (m *QueryCreditBalanceRequest) Size() (n int) { if m == nil { return 0 @@ -2412,7 +3148,511 @@ func (m *QueryIssuersResponse) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryIssuerRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryIssuerRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryIssuerRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IssuerId", wireType) + } + m.IssuerId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.IssuerId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryIssuerResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryIssuerResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryIssuerResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Issuer", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Issuer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryApplicantsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryApplicantsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryApplicantsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryApplicantsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryApplicantsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryApplicantsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Applicants", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Applicants = append(m.Applicants, Applicant{}) + if err := m.Applicants[len(m.Applicants)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryApplicantRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryApplicantRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryApplicantRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplicantId", wireType) + } + m.ApplicantId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ApplicantId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryApplicantResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryApplicantResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryApplicantResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Applicant", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2439,7 +3679,7 @@ func (m *QueryIssuersResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Applicant.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2464,7 +3704,7 @@ func (m *QueryIssuersResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryIssuerRequest) Unmarshal(dAtA []byte) error { +func (m *QueryCreditClassesRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2487,17 +3727,17 @@ func (m *QueryIssuerRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryIssuerRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditClassesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryIssuerRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditClassesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field IssuerId", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } - m.IssuerId = 0 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -2507,11 +3747,25 @@ func (m *QueryIssuerRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.IssuerId |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2533,7 +3787,7 @@ func (m *QueryIssuerRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryIssuerResponse) Unmarshal(dAtA []byte) error { +func (m *QueryCreditClassesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2556,15 +3810,15 @@ func (m *QueryIssuerResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryIssuerResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditClassesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryIssuerResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditClassesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Issuer", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CreditClasses", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2591,7 +3845,41 @@ func (m *QueryIssuerResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Issuer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.CreditClasses = append(m.CreditClasses, CreditClass{}) + if err := m.CreditClasses[len(m.CreditClasses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2616,7 +3904,7 @@ func (m *QueryIssuerResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryApplicantRequest) Unmarshal(dAtA []byte) error { +func (m *QueryCreditClassRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2639,17 +3927,17 @@ func (m *QueryApplicantRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryApplicantRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditClassRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryApplicantRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditClassRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ApplicantId", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CreditClassAbbreviation", wireType) } - m.ApplicantId = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -2659,11 +3947,24 @@ func (m *QueryApplicantRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.ApplicantId |= uint64(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.CreditClassAbbreviation = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -2685,7 +3986,7 @@ func (m *QueryApplicantRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryApplicantResponse) Unmarshal(dAtA []byte) error { +func (m *QueryCreditClassResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2708,15 +4009,15 @@ func (m *QueryApplicantResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryApplicantResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditClassResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryApplicantResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditClassResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Applicant", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CreditClass", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2743,7 +4044,7 @@ func (m *QueryApplicantResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Applicant.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.CreditClass.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2768,7 +4069,7 @@ func (m *QueryApplicantResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditClassesRequest) Unmarshal(dAtA []byte) error { +func (m *QueryProjectsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2791,10 +4092,10 @@ func (m *QueryCreditClassesRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditClassesRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryProjectsRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditClassesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryProjectsRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -2851,7 +4152,7 @@ func (m *QueryCreditClassesRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditClassesResponse) Unmarshal(dAtA []byte) error { +func (m *QueryProjectsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2874,15 +4175,15 @@ func (m *QueryCreditClassesResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditClassesResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryProjectsResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditClassesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryProjectsResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreditClasses", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Projects", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -2909,8 +4210,8 @@ func (m *QueryCreditClassesResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.CreditClasses = append(m.CreditClasses, CreditClass{}) - if err := m.CreditClasses[len(m.CreditClasses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Projects = append(m.Projects, Project{}) + if err := m.Projects[len(m.Projects)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -2968,7 +4269,7 @@ func (m *QueryCreditClassesResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditClassRequest) Unmarshal(dAtA []byte) error { +func (m *QueryProjectRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -2991,17 +4292,17 @@ func (m *QueryCreditClassRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditClassRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryProjectRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditClassRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryProjectRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreditClassAbbreviation", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProjectId", wireType) } - var stringLen uint64 + m.ProjectId = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -3011,24 +4312,11 @@ func (m *QueryCreditClassRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + m.ProjectId |= uint64(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.CreditClassAbbreviation = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -3050,7 +4338,7 @@ func (m *QueryCreditClassRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditClassResponse) Unmarshal(dAtA []byte) error { +func (m *QueryProjectResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3073,15 +4361,15 @@ func (m *QueryCreditClassResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditClassResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryProjectResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditClassResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryProjectResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreditClass", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Project", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -3108,7 +4396,7 @@ func (m *QueryCreditClassResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.CreditClass.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Project.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -3133,7 +4421,7 @@ func (m *QueryCreditClassResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryProjectRequest) Unmarshal(dAtA []byte) error { +func (m *QueryCreditCollectionRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3156,17 +4444,17 @@ func (m *QueryProjectRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryProjectRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditCollectionRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryProjectRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditCollectionRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ProjectId", wireType) + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) } - m.ProjectId = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -3176,11 +4464,24 @@ func (m *QueryProjectRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.ProjectId |= uint64(b&0x7F) << shift + stringLen |= uint64(b&0x7F) << shift if b < 0x80 { break } } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -3202,7 +4503,7 @@ func (m *QueryProjectRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryProjectResponse) Unmarshal(dAtA []byte) error { +func (m *QueryCreditCollectionResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3225,15 +4526,15 @@ func (m *QueryProjectResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryProjectResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditCollectionResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryProjectResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditCollectionResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Project", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CreditCollection", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -3260,7 +4561,7 @@ func (m *QueryProjectResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.Project.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.CreditCollection.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -3285,7 +4586,7 @@ func (m *QueryProjectResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditCollectionRequest) Unmarshal(dAtA []byte) error { +func (m *QueryCreditBalancesRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3308,17 +4609,17 @@ func (m *QueryCreditCollectionRequest) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditCollectionRequest: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditBalancesRequest: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditCollectionRequest: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditBalancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -3328,23 +4629,24 @@ func (m *QueryCreditCollectionRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } - m.Denom = string(dAtA[iNdEx:postIndex]) + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex default: iNdEx = preIndex @@ -3367,7 +4669,7 @@ func (m *QueryCreditCollectionRequest) Unmarshal(dAtA []byte) error { } return nil } -func (m *QueryCreditCollectionResponse) Unmarshal(dAtA []byte) error { +func (m *QueryCreditBalancesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -3390,15 +4692,15 @@ func (m *QueryCreditCollectionResponse) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: QueryCreditCollectionResponse: wiretype end group for non-group") + return fmt.Errorf("proto: QueryCreditBalancesResponse: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: QueryCreditCollectionResponse: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: QueryCreditBalancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CreditCollection", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field CreditBalances", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -3425,7 +4727,41 @@ func (m *QueryCreditCollectionResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.CreditCollection.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.CreditBalances = append(m.CreditBalances, CreditBalance{}) + if err := m.CreditBalances[len(m.CreditBalances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/chain/x/plasticcredit/query.pb.gw.go b/chain/x/plasticcredit/query.pb.gw.go index a69a0ac2b..d615d81a2 100644 --- a/chain/x/plasticcredit/query.pb.gw.go +++ b/chain/x/plasticcredit/query.pb.gw.go @@ -141,6 +141,42 @@ func local_request_Query_Issuer_0(ctx context.Context, marshaler runtime.Marshal } +var ( + filter_Query_Applicants_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Applicants_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryApplicantsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Applicants_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Applicants(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Applicants_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryApplicantsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Applicants_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Applicants(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Applicant_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryApplicantRequest var metadata runtime.ServerMetadata @@ -285,6 +321,42 @@ func local_request_Query_CreditClass_0(ctx context.Context, marshaler runtime.Ma } +var ( + filter_Query_Projects_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Projects_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProjectsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Projects_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Projects(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Projects_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProjectsRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Projects_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Projects(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Project_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryProjectRequest var metadata runtime.ServerMetadata @@ -393,6 +465,42 @@ func local_request_Query_CreditCollection_0(ctx context.Context, marshaler runti } +var ( + filter_Query_CreditBalances_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_CreditBalances_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCreditBalancesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_CreditBalances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.CreditBalances(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_CreditBalances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryCreditBalancesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_CreditBalances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.CreditBalances(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_CreditBalance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryCreditBalanceRequest var metadata runtime.ServerMetadata @@ -544,6 +652,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Applicants_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Applicants_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Applicants_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Applicant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -613,6 +744,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_Projects_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Projects_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Projects_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Project_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -659,6 +813,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_CreditBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_CreditBalances_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_CreditBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_CreditBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -783,6 +960,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Applicants_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Applicants_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Applicants_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Applicant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -843,6 +1040,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_Projects_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Projects_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Projects_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Project_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -883,6 +1100,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_CreditBalances_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_CreditBalances_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_CreditBalances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_CreditBalance_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -913,16 +1150,22 @@ var ( pattern_Query_Issuer_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"empowerchain", "plasticcredit", "issuers", "issuer_id"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Applicants_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2}, []string{"empowerchain", "plasticcredit", "applicants"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Applicant_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"empowerchain", "plasticcredit", "applicants", "applicant_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_CreditClasses_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2}, []string{"empowerchain", "plasticcredit", "credit-classes"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_CreditClass_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"empowerchain", "plasticcredit", "credit-classes", "credit_class_abbreviation"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Projects_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2}, []string{"empowerchain", "plasticcredit", "projects"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Project_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"empowerchain", "plasticcredit", "projects", "project_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_CreditCollection_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"empowerchain", "plasticcredit", "creditcollections", "denom"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_CreditBalances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2}, []string{"empowerchain", "plasticcredit", "creditbalances"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_CreditBalance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4}, []string{"empowerchain", "plasticcredit", "creditbalances", "owner", "denom"}, "", runtime.AssumeColonVerbOpt(false))) ) @@ -933,15 +1176,21 @@ var ( forward_Query_Issuer_0 = runtime.ForwardResponseMessage + forward_Query_Applicants_0 = runtime.ForwardResponseMessage + forward_Query_Applicant_0 = runtime.ForwardResponseMessage forward_Query_CreditClasses_0 = runtime.ForwardResponseMessage forward_Query_CreditClass_0 = runtime.ForwardResponseMessage + forward_Query_Projects_0 = runtime.ForwardResponseMessage + forward_Query_Project_0 = runtime.ForwardResponseMessage forward_Query_CreditCollection_0 = runtime.ForwardResponseMessage + forward_Query_CreditBalances_0 = runtime.ForwardResponseMessage + forward_Query_CreditBalance_0 = runtime.ForwardResponseMessage ) diff --git a/chain/x/plasticcredit/simulation/decoder.go b/chain/x/plasticcredit/simulation/decoder.go new file mode 100644 index 000000000..6df63a1c5 --- /dev/null +++ b/chain/x/plasticcredit/simulation/decoder.go @@ -0,0 +1,64 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" +) + +// NewDecodeStore returns a decoder function closure that unmarshal the KVPair's +// value to the corresponding plasticcredit type. +func NewDecodeStore(cdc codec.Codec) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], plasticcredit.IDCountersKey): + var idCountersA, idCountersB plasticcredit.IDCounters + cdc.MustUnmarshal(kvA.Value, &idCountersA) + cdc.MustUnmarshal(kvB.Value, &idCountersB) + return fmt.Sprintf("%v\n%v", idCountersA, idCountersB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.IssuerKey): + var issuerA, issuerB plasticcredit.Issuer + cdc.MustUnmarshal(kvA.Value, &issuerA) + cdc.MustUnmarshal(kvB.Value, &issuerB) + return fmt.Sprintf("%v\n%v", issuerA, issuerB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.ApplicantKey): + var applicantA, applicantB plasticcredit.Applicant + cdc.MustUnmarshal(kvA.Value, &applicantA) + cdc.MustUnmarshal(kvB.Value, &applicantB) + return fmt.Sprintf("%v\n%v", applicantA, applicantB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.CreditClassKey): + var creditClassA, creditClassB plasticcredit.CreditClass + cdc.MustUnmarshal(kvA.Value, &creditClassA) + cdc.MustUnmarshal(kvB.Value, &creditClassB) + return fmt.Sprintf("%v\n%v", creditClassA, creditClassB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.ProjectKey): + var projectA, projectB plasticcredit.Project + cdc.MustUnmarshal(kvA.Value, &projectA) + cdc.MustUnmarshal(kvB.Value, &projectB) + return fmt.Sprintf("%v\n%v", projectA, projectB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.CreditCollectionKey): + var creditCollectionA, creditCollectionB plasticcredit.CreditCollection + cdc.MustUnmarshal(kvA.Value, &creditCollectionA) + cdc.MustUnmarshal(kvB.Value, &creditCollectionB) + return fmt.Sprintf("%v\n%v", creditCollectionA, creditCollectionB) + + case bytes.Equal(kvA.Key[:1], plasticcredit.CreditBalanceKey): + var creditBalanceA, creditBalanceB plasticcredit.CreditBalance + cdc.MustUnmarshal(kvA.Value, &creditBalanceA) + cdc.MustUnmarshal(kvB.Value, &creditBalanceB) + return fmt.Sprintf("%v\n%v", creditBalanceA, creditBalanceB) + + default: + panic(fmt.Sprintf("invalid plasticcredit key %X", kvA.Key)) + } + } +} diff --git a/chain/x/plasticcredit/simulation/decoder_test.go b/chain/x/plasticcredit/simulation/decoder_test.go new file mode 100644 index 000000000..53860d7a4 --- /dev/null +++ b/chain/x/plasticcredit/simulation/decoder_test.go @@ -0,0 +1,151 @@ +package simulation_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/stretchr/testify/require" + + "github.com/EmpowerPlastic/empowerchain/app" + "github.com/EmpowerPlastic/empowerchain/app/params" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/simulation" +) + +func TestNewDecodeStore(t *testing.T) { + cdc := params.MakeEncodingConfig(app.ModuleBasics).Codec + decodeStore := simulation.NewDecodeStore(cdc) + + idCounters := plasticcredit.IDCounters{ + NextIssuerId: 1, + NextApplicantId: 69, + NextProjectId: 42, + } + issuer := plasticcredit.Issuer{ + Id: 1, + Name: "test issuer", + Description: "test issuer description", + Admin: "empower18hl5c9xn5dze2g50uaw0l2mr02ew57zkk9vga7", + } + applicant := plasticcredit.Applicant{ + Id: 1, + Name: "test applicant", + Description: "test applicant description", + Admin: "empower18hl5c9xn5dze2g50uaw0l2mr02ew57zkk9vga7", + } + creditClass := plasticcredit.CreditClass{ + Abbreviation: "PCRD", + IssuerId: 1, + Name: "test credit class", + } + project := plasticcredit.Project{ + Id: 1, + ApplicantId: 1, + CreditClassAbbreviation: "PCRD", + Name: "test project", + Status: plasticcredit.ProjectStatus_NEW, + } + creditCollection := plasticcredit.CreditCollection{ + Denom: "PCRD", + ProjectId: 1, + TotalAmount: plasticcredit.CreditAmount{ + Active: 12, + Retired: 3, + }, + } + creditBalance := plasticcredit.CreditBalance{ + Owner: "empower18hl5c9xn5dze2g50uaw0l2mr02ew57zkk9vga7", + Denom: "PCRD", + Balance: plasticcredit.CreditAmount{ + Active: 3, + Retired: 2, + }, + } + + testCases := map[string]struct { + kvPair kv.Pair // we use the same kv pair as both a and b + expectErr bool + expectedValue string + }{ + "id counters": { + kvPair: kv.Pair{ + Key: plasticcredit.IDCountersKey, + Value: cdc.MustMarshal(&idCounters), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", idCounters, idCounters), + }, + "issuer": { + kvPair: kv.Pair{ + Key: plasticcredit.IssuerKey, + Value: cdc.MustMarshal(&issuer), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", issuer, issuer), + }, + "applicant": { + kvPair: kv.Pair{ + Key: plasticcredit.ApplicantKey, + Value: cdc.MustMarshal(&applicant), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", applicant, applicant), + }, + "credit class": { + kvPair: kv.Pair{ + Key: plasticcredit.CreditClassKey, + Value: cdc.MustMarshal(&creditClass), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", creditClass, creditClass), + }, + "project": { + kvPair: kv.Pair{ + Key: plasticcredit.ProjectKey, + Value: cdc.MustMarshal(&project), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", project, project), + }, + "credit collection": { + kvPair: kv.Pair{ + Key: plasticcredit.CreditCollectionKey, + Value: cdc.MustMarshal(&creditCollection), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", creditCollection, creditCollection), + }, + "credit balance": { + kvPair: kv.Pair{ + Key: plasticcredit.CreditBalanceKey, + Value: cdc.MustMarshal(&creditBalance), + }, + expectErr: false, + expectedValue: fmt.Sprintf("%v\n%v", creditBalance, creditBalance), + }, + "empty": { + kvPair: kv.Pair{}, + expectErr: true, + expectedValue: "", + }, + "non-existent key": { + kvPair: kv.Pair{ + Key: []byte("non-existent key"), + Value: cdc.MustMarshal(&idCounters), + }, + expectErr: true, + expectedValue: "", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + if tc.expectErr { + require.Panics(t, func() { decodeStore(tc.kvPair, tc.kvPair) }) + } else { + require.Equal(t, tc.expectedValue, decodeStore(tc.kvPair, tc.kvPair)) + } + }) + } +} diff --git a/chain/x/plasticcredit/simulation/genesis.go b/chain/x/plasticcredit/simulation/genesis.go new file mode 100644 index 000000000..a9415b512 --- /dev/null +++ b/chain/x/plasticcredit/simulation/genesis.go @@ -0,0 +1,310 @@ +package simulation + +import ( + "fmt" + "math/rand" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/keeper" +) + +const ( + IssuerCreatorKey = "issuer-creator" + IssuerCreatorFeeKey = "issuer-creator-fee" + IssuersKey = "issuers" + ApplicantsKey = "applicants" + CreditClassesKey = "credit-classes" + ProjectsKey = "projects" + CreditCollectionsKey = "credit-collections" + CreditBalancesKey = "credit-balances" +) + +// RandomizedGenState generates a random GenesisState for plasticcredit +func RandomizedGenState(simState *module.SimulationState) { + var issuerCreator string + simState.AppParams.GetOrGenerate( + simState.Cdc, IssuerCreatorKey, &issuerCreator, simState.Rand, + func(r *rand.Rand) { issuerCreator = generateIssuerCreator(r, simState.Accounts) }, + ) + + var issuerCreatorFee int + simState.AppParams.GetOrGenerate( + simState.Cdc, IssuerCreatorFeeKey, &issuerCreatorFee, simState.Rand, + func(r *rand.Rand) { issuerCreatorFee = simtypes.RandIntBetween(r, 1, 10000) }, + ) + + params := plasticcredit.NewParams(issuerCreator, sdk.NewCoin(simState.BondDenom, math.NewInt(int64(issuerCreatorFee)))) + + var issuers []plasticcredit.Issuer + simState.AppParams.GetOrGenerate( + simState.Cdc, IssuersKey, &issuers, simState.Rand, + func(r *rand.Rand) { issuers = generateIssuers(r, simState.Accounts) }, + ) + + var applicants []plasticcredit.Applicant + simState.AppParams.GetOrGenerate( + simState.Cdc, ApplicantsKey, &applicants, simState.Rand, + func(r *rand.Rand) { applicants = generateApplicants(r, simState.Accounts) }, + ) + + var creditClasses []plasticcredit.CreditClass + simState.AppParams.GetOrGenerate( + simState.Cdc, CreditClassesKey, &creditClasses, simState.Rand, + func(r *rand.Rand) { creditClasses = generateCreditClasses(r, issuers) }, + ) + + var projects []plasticcredit.Project + simState.AppParams.GetOrGenerate( + simState.Cdc, ProjectsKey, &projects, simState.Rand, + func(r *rand.Rand) { projects = generateProjects(r, applicants, creditClasses) }, + ) + + var creditCollections []plasticcredit.CreditCollection + simState.AppParams.GetOrGenerate( + simState.Cdc, CreditCollectionsKey, &creditCollections, simState.Rand, + func(r *rand.Rand) { creditCollections = generateCreditCollections(r, projects) }, + ) + + var creditBalances []plasticcredit.CreditBalance + simState.AppParams.GetOrGenerate( + simState.Cdc, CreditBalancesKey, &creditBalances, simState.Rand, + func(r *rand.Rand) { creditBalances = generateCreditBalances(r, simState.Accounts, creditCollections) }, + ) + + plasticcreditGenesis := plasticcredit.GenesisState{ + Params: params, + IdCounters: plasticcredit.IDCounters{ + NextIssuerId: uint64(len(issuers) + 1), + NextApplicantId: uint64(len(applicants) + 1), + NextProjectId: uint64(len(projects) + 1), + }, + Issuers: issuers, + Applicants: applicants, + CreditClasses: creditClasses, + Projects: projects, + CreditCollections: creditCollections, + CreditBalances: creditBalances, + } + + fmt.Println("Number of issuers: ", len(issuers)) + fmt.Println("Number of applicants: ", len(applicants)) + fmt.Println("Number of credit classes: ", len(creditClasses)) + fmt.Println("Number of projects: ", len(projects)) + fmt.Println("Number of credit collections: ", len(creditCollections)) + fmt.Println("Number of credit balances: ", len(creditBalances)) + + if err := plasticcreditGenesis.Validate(); err != nil { + panic(err) + } + + simState.GenState[plasticcredit.ModuleName] = simState.Cdc.MustMarshalJSON(&plasticcreditGenesis) +} + +func generateIssuerCreator(r *rand.Rand, accounts []simtypes.Account) string { + isGovernanceControlled := simtypes.RandIntBetween(r, 1, 10) == 1 // 10% chance + if isGovernanceControlled { + return "" + } + + acc, _ := simtypes.RandomAcc(r, accounts) + return acc.Address.String() +} + +func generateIssuers(r *rand.Rand, accounts []simtypes.Account) []plasticcredit.Issuer { + var issuers []plasticcredit.Issuer + + numIssuers := simtypes.RandIntBetween(r, 1, Min(20, len(accounts))) + for i := 0; i < numIssuers; i++ { + acc, _ := simtypes.RandomAcc(r, accounts) + issuers = append(issuers, plasticcredit.Issuer{ + Id: uint64(i + 1), + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: acc.Address.String(), + }) + } + + return issuers +} + +func Min(x, y int) int { + if x < y { + return x + } + return y +} + +func generateApplicants(r *rand.Rand, accounts []simtypes.Account) []plasticcredit.Applicant { + var applicants []plasticcredit.Applicant + numApplicants := simtypes.RandIntBetween(r, 1, Min(500, len(accounts))) + for i := 0; i < numApplicants; i++ { + acc, _ := simtypes.RandomAcc(r, accounts) + applicants = append(applicants, plasticcredit.Applicant{ + Id: uint64(i + 1), + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: acc.Address.String(), + }) + } + + return applicants +} + +func generateCreditClasses(r *rand.Rand, issuers []plasticcredit.Issuer) []plasticcredit.CreditClass { + var creditClasses []plasticcredit.CreditClass + usedAbbreviations := make(map[string]bool) + + for i := 0; i < len(issuers); i++ { + numberOfCreditClasses := simtypes.RandIntBetween(r, 1, 3) + + for j := 0; j < numberOfCreditClasses; j++ { + var abbreviation string + for { + abbreviation = createRandomAbbreviation(r) + if _, ok := usedAbbreviations[abbreviation]; !ok { + usedAbbreviations[abbreviation] = true + break + } + } + + creditClasses = append(creditClasses, plasticcredit.CreditClass{ + Abbreviation: abbreviation, + IssuerId: issuers[i].Id, + Name: createRandomName(r), + }) + } + } + + return creditClasses +} + +func generateProjects(r *rand.Rand, applicants []plasticcredit.Applicant, creditClasses []plasticcredit.CreditClass) []plasticcredit.Project { + var projects []plasticcredit.Project + + if len(applicants) == 0 || len(creditClasses) == 0 { + return projects + } + + nextProjectID := 1 + for i := 0; i < len(applicants); i++ { + numberOfProjectsForApplicant := simtypes.RandIntBetween(r, 1, 3) + + for j := 0; j < numberOfProjectsForApplicant; j++ { + creditClass := creditClasses[simtypes.RandIntBetween(r, 0, len(creditClasses))] + + projects = append(projects, plasticcredit.Project{ + Id: uint64(nextProjectID), + ApplicantId: applicants[i].Id, + CreditClassAbbreviation: creditClass.Abbreviation, + Name: createRandomName(r), + Status: plasticcredit.ProjectStatus(simtypes.RandIntBetween(r, 0, 3)), + }) + + nextProjectID++ + } + } + + return projects +} + +func generateCreditCollections(r *rand.Rand, projects []plasticcredit.Project) []plasticcredit.CreditCollection { + var creditCollections []plasticcredit.CreditCollection + usedDenom := make(map[string]bool) + + for i := 0; i < len(projects); i++ { + numberOfCollectionsForProject := simtypes.RandIntBetween(r, 0, 5) + for j := 0; j < numberOfCollectionsForProject; j++ { + + var denom string + for { + serialNumber := createRandomSerialNumber(r) + denom, _ = keeper.CreateCreditDenom(projects[i].CreditClassAbbreviation, serialNumber) + if _, ok := usedDenom[denom]; !ok { + usedDenom[denom] = true + break + } + } + + active := uint64(simtypes.RandIntBetween(r, 1, 1000000)) + retired := uint64(simtypes.RandIntBetween(r, 1, 1000000)) + // 10% chance for all to be active + if simtypes.RandIntBetween(r, 1, 10) == 1 { + retired = 0 + } + + // 10% chance for all to be retired (if not all active) + if retired != 0 && simtypes.RandIntBetween(r, 1, 10) == 1 { + active = 0 + } + + creditCollections = append(creditCollections, plasticcredit.CreditCollection{ + Denom: denom, + ProjectId: projects[i].Id, + TotalAmount: plasticcredit.CreditAmount{ + Active: active, + Retired: retired, + }, + }) + } + } + + return creditCollections +} + +func generateCreditBalances(r *rand.Rand, accounts []simtypes.Account, creditCollections []plasticcredit.CreditCollection) []plasticcredit.CreditBalance { + var creditBalances []plasticcredit.CreditBalance + + for _, creditCollection := range creditCollections { + activeLeft := creditCollection.TotalAmount.Active + retiredLeft := creditCollection.TotalAmount.Retired + numberOfAccounts := simtypes.RandIntBetween(r, 1, Min(500, len(accounts))) + // 10% chance for all to be on one account + if simtypes.RandIntBetween(r, 1, 10) == 1 { + numberOfAccounts = 1 + } + + var usedAccounts []simtypes.Account + for i := 0; i < numberOfAccounts; i++ { + acc := getUnusedAccount(r, accounts, usedAccounts) + usedAccounts = append(usedAccounts, acc) + var active, retired uint64 + // On the last account, give the rest of the credits + if i == numberOfAccounts-1 { + active = activeLeft + retired = retiredLeft + } else { + active = uint64(safeRandIntBetween(r, 0, int(activeLeft))) + retired = uint64(safeRandIntBetween(r, 0, int(retiredLeft))) + } + + creditBalances = append(creditBalances, plasticcredit.CreditBalance{ + Owner: acc.Address.String(), + Denom: creditCollection.Denom, + Balance: plasticcredit.CreditAmount{ + Active: active, + Retired: retired, + }, + }) + + activeLeft -= active + retiredLeft -= retired + } + } + + return creditBalances +} + +func getUnusedAccount(r *rand.Rand, accounts []simtypes.Account, usedAccounts []simtypes.Account) simtypes.Account { + for { + acc, _ := simtypes.RandomAcc(r, accounts) + _, found := simtypes.FindAccount(usedAccounts, acc.Address) + if !found { + return acc + } + } +} diff --git a/chain/x/plasticcredit/simulation/genesis_test.go b/chain/x/plasticcredit/simulation/genesis_test.go new file mode 100644 index 000000000..4beb99f6e --- /dev/null +++ b/chain/x/plasticcredit/simulation/genesis_test.go @@ -0,0 +1,51 @@ +package simulation_test + +import ( + "encoding/json" + "math/rand" + "testing" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/stretchr/testify/assert" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/simulation" +) + +func TestRandomizedGenState(t *testing.T) { + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + s := rand.NewSource(1) + r := rand.New(s) + + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + Rand: r, + NumBonded: 3, + BondDenom: sdk.DefaultBondDenom, + Accounts: simtypes.RandomAccounts(r, 3), + InitialStake: sdkmath.NewInt(1000), + GenState: make(map[string]json.RawMessage), + } + + simulation.RandomizedGenState(&simState) + + var plasticcreditGenesis plasticcredit.GenesisState + simState.Cdc.MustUnmarshalJSON(simState.GenState[plasticcredit.ModuleName], &plasticcreditGenesis) + + assert.NotEmpty(t, plasticcreditGenesis.Params.IssuerCreator) + assert.NotEmpty(t, plasticcreditGenesis.Issuers) + assert.NotEmpty(t, plasticcreditGenesis.Applicants) + assert.NotEmpty(t, plasticcreditGenesis.CreditClasses) + assert.NotEmpty(t, plasticcreditGenesis.Projects) + assert.NotEmpty(t, plasticcreditGenesis.CreditCollections) + assert.NotEmpty(t, plasticcreditGenesis.CreditBalances) + + assert.NoError(t, plasticcreditGenesis.Validate()) +} diff --git a/chain/x/plasticcredit/simulation/operations.go b/chain/x/plasticcredit/simulation/operations.go new file mode 100644 index 000000000..2a3fc651b --- /dev/null +++ b/chain/x/plasticcredit/simulation/operations.go @@ -0,0 +1,957 @@ +package simulation + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/keeper" +) + +//nolint:gosec +const ( + DefaultWeightMsgCreateIssuer = 10 + DefaultWeightMsgUpdateIssuer = 20 + DefaultWeightMsgCreateApplicant = 75 + DefaultWeightMsgUpdateApplicant = 50 + DefaultWeightMsgCreateCreditClass = 10 + DefaultWeightMsgUpdateCreditClass = 5 + DefaultWeightMsgCreateProject = 70 + DefaultWeightMsgUpdateProject = 30 + DefaultWeightMsgApproveProject = 20 + DefaultWeightMsgRejectProject = 30 + DefaultWeightMsgSuspendProject = 10 + DefaultWeightMsgIssueCredits = 75 + DefaultWeightMsgTransferCredits = 15 // Low for now, the lookup is too expensive + DefaultWeightMsgRetireCredits = 15 // Low for now, the lookup is too expensive + + OpWeightMsgCreateIssuer = "op_weight_msg_create_issuer" + OpWeightMsgUpdateIssuer = "op_weight_msg_update_issuer" + OpWeightMsgCreateApplicant = "op_weight_msg_create_applicant" + OpWeightMsgUpdateApplicant = "op_weight_msg_update_applicant" + OpWeightMsgCreateCreditClass = "op_weight_msg_create_credit_class" + OpWeightMsgUpdateCreditClass = "op_weight_msg_update_credit_class" + OpWeightMsgCreateProject = "op_weight_msg_create_project" + OpWeightMsgUpdateProject = "op_weight_msg_update_project" + OpWeightMsgApproveProject = "op_weight_msg_approve_project" + OpWeightMsgRejectProject = "op_weight_msg_reject_project" + OpWeightMsgSuspendProject = "op_weight_msg_suspend_project" + OpWeightMsgIssueCredits = "op_weight_msg_issue_credits" + OpWeightMsgTransferCredits = "op_weight_msg_transfer_credits" + OpWeightMsgRetireCredits = "op_weight_msg_retire_credits" +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, + cdc codec.JSONCodec, + ak plasticcredit.AccountKeeper, + bk plasticcredit.BankKeeper, + k keeper.Keeper, +) simulation.WeightedOperations { + var ( + weightMsgCreateIssuer int + weightMsgUpdateIssuer int + weightMsgCreateApplicant int + weightMsgUpdateApplicant int + weightMsgCreateCreditClass int + weightMsgUpdateCreditClass int + weightMsgCreateProject int + weightMsgUpdateProject int + weightMsgApproveProject int + weightMsgRejectProject int + weightMsgSuspendProject int + weightMsgIssueCredits int + weightMsgTransferCredits int + weightMsgRetireCredits int + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgCreateIssuer, &weightMsgCreateIssuer, nil, + func(_ *rand.Rand) { + weightMsgCreateIssuer = DefaultWeightMsgCreateIssuer + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgUpdateIssuer, &weightMsgUpdateIssuer, nil, + func(_ *rand.Rand) { + weightMsgUpdateIssuer = DefaultWeightMsgUpdateIssuer + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgCreateApplicant, &weightMsgCreateApplicant, nil, + func(_ *rand.Rand) { + weightMsgCreateApplicant = DefaultWeightMsgCreateApplicant + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgUpdateApplicant, &weightMsgUpdateApplicant, nil, + func(_ *rand.Rand) { + weightMsgUpdateApplicant = DefaultWeightMsgUpdateApplicant + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgCreateCreditClass, &weightMsgCreateCreditClass, nil, + func(_ *rand.Rand) { + weightMsgCreateCreditClass = DefaultWeightMsgCreateCreditClass + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgUpdateCreditClass, &weightMsgUpdateCreditClass, nil, + func(_ *rand.Rand) { + weightMsgUpdateCreditClass = DefaultWeightMsgUpdateCreditClass + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgCreateProject, &weightMsgCreateProject, nil, + func(_ *rand.Rand) { + weightMsgCreateProject = DefaultWeightMsgCreateProject + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgUpdateProject, &weightMsgUpdateProject, nil, + func(_ *rand.Rand) { + weightMsgUpdateProject = DefaultWeightMsgUpdateProject + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgApproveProject, &weightMsgApproveProject, nil, + func(_ *rand.Rand) { + weightMsgApproveProject = DefaultWeightMsgApproveProject + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgRejectProject, &weightMsgRejectProject, nil, + func(_ *rand.Rand) { + weightMsgRejectProject = DefaultWeightMsgRejectProject + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgSuspendProject, &weightMsgSuspendProject, nil, + func(_ *rand.Rand) { + weightMsgSuspendProject = DefaultWeightMsgSuspendProject + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgIssueCredits, &weightMsgIssueCredits, nil, + func(_ *rand.Rand) { + weightMsgIssueCredits = DefaultWeightMsgIssueCredits + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgTransferCredits, &weightMsgTransferCredits, nil, + func(_ *rand.Rand) { + weightMsgTransferCredits = DefaultWeightMsgTransferCredits + }, + ) + appParams.GetOrGenerate(cdc, OpWeightMsgRetireCredits, &weightMsgRetireCredits, nil, + func(_ *rand.Rand) { + weightMsgRetireCredits = DefaultWeightMsgRetireCredits + }, + ) + + protoCodec := cdc.(*codec.ProtoCodec) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgCreateIssuer, + SimulateMsgCreateIssuer(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgUpdateIssuer, + SimulateMsgUpdateIssuer(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgCreateApplicant, + SimulateMsgCreateApplicant(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgUpdateApplicant, + SimulateMsgUpdateApplicant(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgCreateCreditClass, + SimulateMsgCreateCreditClass(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgUpdateCreditClass, + SimulateMsgUpdateCreditClass(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgCreateProject, + SimulateMsgCreateProject(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgUpdateProject, + SimulateMsgUpdateProject(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgApproveProject, + SimulateMsgApproveProject(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgRejectProject, + SimulateMsgRejectProject(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgSuspendProject, + SimulateMsgSuspendProject(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgIssueCredits, + SimulateMsgIssueCredits(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgTransferCredits, + SimulateMsgTransferCredits(protoCodec, ak, bk, k), + ), + simulation.NewWeightedOperation( + weightMsgRetireCredits, + SimulateMsgRetireCredits(protoCodec, ak, bk, k), + ), + } +} + +// SimulateMsgCreateIssuer generates a MsgCreateIssuer with random values. +func SimulateMsgCreateIssuer(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgCreateIssuer{}) + querier := keeper.Querier{Keeper: k} + admin, _ := simtypes.RandomAcc(r, accounts) + + ctx := sdk.WrapSDKContext(sdkCtx) + res, err := querier.Params(ctx, &plasticcredit.QueryParamsRequest{}) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get params"), nil, nil + } + + if res.Params.IssuerCreator == "" { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "issuer creator not set"), nil, nil + } + + simAccount, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(res.Params.IssuerCreator)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "issuer creator not found"), nil, nil + } + + msg := &plasticcredit.MsgCreateIssuer{ + Creator: simAccount.Address.String(), + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: admin.Address.String(), + } + + spendable := bk.SpendableCoins(sdkCtx, simAccount.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: simAccount, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +// SimulateMsgUpdateIssuer generates a MsgUpdateIssuer with random values. +func SimulateMsgUpdateIssuer(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgUpdateIssuer{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + ids := querier.GetIDCounters(sdkCtx) + issuer, err := getRandomIssuer(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgUpdateIssuer{ + Updater: admin.Address.String(), + IssuerId: issuer.Id, + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: admin.Address.String(), + } + + spendable := bk.SpendableCoins(sdkCtx, admin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +// SimulateMsgCreateApplicant generates a MsgCreateApplicant with random values. +func SimulateMsgCreateApplicant(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, _ keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgUpdateIssuer{}) + simAccount, _ := simtypes.RandomAcc(r, accounts) + admin, _ := simtypes.RandomAcc(r, accounts) + + msg := &plasticcredit.MsgCreateApplicant{ + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: admin.Address.String(), + } + + spendable := bk.SpendableCoins(sdkCtx, simAccount.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +// SimulateMsgUpdateApplicant generates a MsgUpdateApplicant with random values. +func SimulateMsgUpdateApplicant(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgUpdateApplicant{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + ids := querier.GetIDCounters(sdkCtx) + applicant, err := getRandomApplicant(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get applicant"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(applicant.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgUpdateApplicant{ + Updater: admin.Address.String(), + ApplicantId: applicant.Id, + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: admin.Address.String(), + } + + spendable := bk.SpendableCoins(sdkCtx, admin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +// SimulateMsgCreateCreditClass generates a MsgCreateCreditClass with random values. +func SimulateMsgCreateCreditClass(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgCreateCreditClass{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + issuer, err := getRandomIssuer(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgCreateCreditClass{ + Creator: admin.Address.String(), + Abbreviation: createUniqueRandomAbbreviation(ctx, r, querier), + IssuerId: issuer.Id, + Name: createRandomName(r), + } + + res, _ := querier.Params(ctx, &plasticcredit.QueryParamsRequest{}) + params := res.Params + + spendable, neg := bk.SpendableCoins(sdkCtx, admin.Address).SafeSub(params.CreditClassCreationFee) + if neg { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "not enough balance to create credit class"), nil, nil + } + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +// SimulateMsgUpdateCreditClass generates a MsgUpdateCreditClass with random values. +func SimulateMsgUpdateCreditClass(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgUpdateCreditClass{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + creditClass, err := getRandomCreditClass(ctx, r, querier) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + issuer, found := querier.GetIssuer(sdkCtx, creditClass.IssuerId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find issuer"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgUpdateCreditClass{ + Updater: admin.Address.String(), + Abbreviation: creditClass.Abbreviation, + Name: createRandomName(r), + } + + spendable := bk.SpendableCoins(sdkCtx, admin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgCreateProject(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgCreateProject{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + applicant, err := getRandomApplicant(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get applicant"), nil, nil + } + + creditClass, err := getRandomCreditClass(ctx, r, querier) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit class"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(applicant.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgCreateProject{ + Creator: admin.Address.String(), + ApplicantId: applicant.Id, + CreditClassAbbreviation: creditClass.Abbreviation, + Name: createRandomName(r), + } + + spendable := bk.SpendableCoins(sdkCtx, admin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgUpdateProject(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgUpdateProject{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + project, err := getRandomProject(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get project"), nil, nil + } + + applicant, found := querier.GetApplicant(sdkCtx, project.ApplicantId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get applicant"), nil, nil + } + + admin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(applicant.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgUpdateProject{ + Updater: admin.Address.String(), + ProjectId: project.Id, + Name: createRandomName(r), + } + + spendable := bk.SpendableCoins(sdkCtx, admin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: admin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgApproveProject(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgApproveProject{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + project, err := getRandomProject(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get project"), nil, nil + } + if project.Status == plasticcredit.ProjectStatus_APPROVED { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "project already approved"), nil, nil + } + + creditClass, found := querier.GetCreditClass(sdkCtx, project.CreditClassAbbreviation) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit class"), nil, nil + } + + issuer, found := querier.GetIssuer(sdkCtx, creditClass.IssuerId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + issuerAdmin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgApproveProject{ + Approver: issuerAdmin.Address.String(), + ProjectId: project.Id, + } + + spendable := bk.SpendableCoins(sdkCtx, issuerAdmin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: issuerAdmin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgRejectProject(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgRejectProject{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + project, err := getRandomProject(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get project"), nil, nil + } + if project.Status != plasticcredit.ProjectStatus_NEW { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "project cannot be rejected"), nil, nil + } + + creditClass, found := querier.GetCreditClass(sdkCtx, project.CreditClassAbbreviation) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit class"), nil, nil + } + + issuer, found := querier.GetIssuer(sdkCtx, creditClass.IssuerId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + issuerAdmin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgRejectProject{ + Rejector: issuerAdmin.Address.String(), + ProjectId: project.Id, + } + + spendable := bk.SpendableCoins(sdkCtx, issuerAdmin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: issuerAdmin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgSuspendProject(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgSuspendProject{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + project, err := getRandomProject(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get project"), nil, nil + } + if project.Status != plasticcredit.ProjectStatus_APPROVED { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "project cannot be suspended"), nil, nil + } + + creditClass, found := querier.GetCreditClass(sdkCtx, project.CreditClassAbbreviation) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit class"), nil, nil + } + + issuer, found := querier.GetIssuer(sdkCtx, creditClass.IssuerId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + issuerAdmin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgSuspendProject{ + Updater: issuerAdmin.Address.String(), + ProjectId: project.Id, + } + + spendable := bk.SpendableCoins(sdkCtx, issuerAdmin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: issuerAdmin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgIssueCredits(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgIssueCredits{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + ids := querier.GetIDCounters(sdkCtx) + project, err := getRandomProject(ctx, r, querier, ids) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get project"), nil, nil + } + if project.Status != plasticcredit.ProjectStatus_APPROVED { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "cannot issue credit for non-approved project"), nil, nil + } + + creditClass, found := querier.GetCreditClass(sdkCtx, project.CreditClassAbbreviation) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit class"), nil, nil + } + + issuer, found := querier.GetIssuer(sdkCtx, creditClass.IssuerId) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get issuer"), nil, nil + } + + issuerAdmin, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(issuer.Admin)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find admin"), nil, nil + } + + msg := &plasticcredit.MsgIssueCredits{ + Creator: issuerAdmin.Address.String(), + ProjectId: project.Id, + SerialNumber: createUniqueRandomSerialNumber(ctx, r, querier, creditClass.Abbreviation), + CreditAmount: uint64(simtypes.RandIntBetween(r, 1, 10000000)), + } + + spendable := bk.SpendableCoins(sdkCtx, issuerAdmin.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: issuerAdmin, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgTransferCredits(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgTransferCredits{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + creditBalance, err := getRandomCreditBalance(ctx, r, querier) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit balance"), nil, nil + } + + owner, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(creditBalance.Owner)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find owner"), nil, nil + } + recipient, _ := simtypes.RandomAcc(r, accounts) + if owner.Equals(recipient) { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "cannot transfer credits to self"), nil, nil + } + + if creditBalance.Balance.Active == 0 { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "no active credits to transfer"), nil, nil + } + + amount := 1 + if creditBalance.Balance.Active > 1 { + amount = simtypes.RandIntBetween(r, 1, int(creditBalance.Balance.Active)) + } + + msg := &plasticcredit.MsgTransferCredits{ + From: owner.Address.String(), + To: recipient.Address.String(), + Denom: creditBalance.Denom, + Amount: uint64(amount), + Retire: simtypes.RandIntBetween(r, 0, 1) == 1, + } + + spendable := bk.SpendableCoins(sdkCtx, owner.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: owner, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} + +func SimulateMsgRetireCredits(cdc *codec.ProtoCodec, ak plasticcredit.AccountKeeper, bk plasticcredit.BankKeeper, k keeper.Keeper) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string, + ) (opMsg simtypes.OperationMsg, fOps []simtypes.FutureOperation, err error) { + msgType := sdk.MsgTypeURL(&plasticcredit.MsgRetireCredits{}) + querier := keeper.Querier{Keeper: k} + + ctx := sdk.WrapSDKContext(sdkCtx) + + creditBalance, err := getRandomCreditBalance(ctx, r, querier) + if err != nil { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to get credit balance"), nil, nil + } + + owner, found := simtypes.FindAccount(accounts, sdk.MustAccAddressFromBech32(creditBalance.Owner)) + if !found { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "unable to find owner"), nil, nil + } + + if creditBalance.Balance.Active == 0 { + return simtypes.NoOpMsg(plasticcredit.ModuleName, msgType, "no active credits to retire"), nil, nil + } + + amount := 1 + if creditBalance.Balance.Active > 1 { + amount = simtypes.RandIntBetween(r, 1, int(creditBalance.Balance.Active)) + } + + msg := &plasticcredit.MsgRetireCredits{ + Owner: owner.Address.String(), + Denom: creditBalance.Denom, + Amount: uint64(amount), + } + + spendable := bk.SpendableCoins(sdkCtx, owner.Address) + + txCtx := simulation.OperationInput{ + R: r, + App: app, + TxGen: moduletestutil.MakeTestEncodingConfig().TxConfig, + Cdc: cdc, + Msg: msg, + MsgType: msgType, + Context: sdkCtx, + SimAccount: owner, + AccountKeeper: ak, + Bankkeeper: bk, + ModuleName: plasticcredit.ModuleName, + CoinsSpentInMsg: spendable, + } + + return simulation.GenAndDeliverTxWithRandFees(txCtx) + } +} diff --git a/chain/x/plasticcredit/simulation/operations_test.go b/chain/x/plasticcredit/simulation/operations_test.go new file mode 100644 index 000000000..5c6452f9a --- /dev/null +++ b/chain/x/plasticcredit/simulation/operations_test.go @@ -0,0 +1 @@ +package simulation_test diff --git a/chain/x/plasticcredit/simulation/proposals.go b/chain/x/plasticcredit/simulation/proposals.go new file mode 100644 index 000000000..a6d566dc5 --- /dev/null +++ b/chain/x/plasticcredit/simulation/proposals.go @@ -0,0 +1,68 @@ +package simulation + +import ( + "math/rand" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" +) + +// Simulation operation weights constants +const ( + DefaultWeightMsgUpdateParamsProposal int = 100 + DefaultWeightMsgCreateIssuerProposal int = 10 + + OpWeightMsgUpdateParamsProposal = "op_weight_msg_update_params_proposal" //nolint:gosec + OpWeightMsgCreateIssuerProposal = "op_weight_msg_create_issuer_proposal" //nolint:gosec +) + +// ProposalMsgs defines the module weighted proposals' contents +func ProposalMsgs() []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{ + simulation.NewWeightedProposalMsg( + OpWeightMsgUpdateParamsProposal, + DefaultWeightMsgUpdateParamsProposal, + SimulateMsgUpdateParamsForProposal, + ), + simulation.NewWeightedProposalMsg( + OpWeightMsgCreateIssuerProposal, + DefaultWeightMsgCreateIssuerProposal, + SimulateMsgCreateIssuerForProposal, + ), + } +} + +// SimulateMsgUpdateParamsForProposal returns a random MsgUpdateParams +func SimulateMsgUpdateParamsForProposal(r *rand.Rand, _ sdk.Context, accounts []simtypes.Account) sdk.Msg { + // use the default gov module account address as authority + var authority sdk.AccAddress = address.Module("gov") + + params := plasticcredit.DefaultParams() + params.IssuerCreator = generateIssuerCreator(r, accounts) + + return &plasticcredit.MsgUpdateParams{ + Authority: authority.String(), + Params: params, + } +} + +// SimulateMsgCreateIssuerForProposal returns a random MsgCreateIssuer with the default gov module account as authority +func SimulateMsgCreateIssuerForProposal(r *rand.Rand, _ sdk.Context, accounts []simtypes.Account) sdk.Msg { + // use the default gov module account address as authority + var authority sdk.AccAddress = address.Module("gov") + admin, _ := simtypes.RandomAcc(r, accounts) + + params := plasticcredit.DefaultParams() + params.IssuerCreator = generateIssuerCreator(r, accounts) + + return &plasticcredit.MsgCreateIssuer{ + Creator: authority.String(), + Name: createRandomName(r), + Description: createRandomDescription(r), + Admin: admin.Address.String(), + } +} diff --git a/chain/x/plasticcredit/simulation/proposals_test.go b/chain/x/plasticcredit/simulation/proposals_test.go new file mode 100644 index 000000000..1b02b94b7 --- /dev/null +++ b/chain/x/plasticcredit/simulation/proposals_test.go @@ -0,0 +1,50 @@ +package simulation_test + +import ( + "math/rand" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/stretchr/testify/require" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/simulation" +) + +func TestProposalMsgs(t *testing.T) { + // initialize parameters + s := rand.NewSource(1) + r := rand.New(s) + + ctx := sdk.NewContext(nil, tmproto.Header{}, true, nil) + accounts := simtypes.RandomAccounts(r, 3) + + // execute ProposalMsgs function + weightedProposalMsgs := simulation.ProposalMsgs() + require.Len(t, weightedProposalMsgs, 2) + + paramsProposalOperation := weightedProposalMsgs[0] + // tests paramsProposalOperation interface: + require.Equal(t, simulation.OpWeightMsgUpdateParamsProposal, paramsProposalOperation.AppParamsKey()) + require.Equal(t, simulation.DefaultWeightMsgUpdateParamsProposal, paramsProposalOperation.DefaultWeight()) + + paramsProposalMsg := paramsProposalOperation.MsgSimulatorFn()(r, ctx, accounts) + msgUpdateParams, ok := paramsProposalMsg.(*plasticcredit.MsgUpdateParams) + require.True(t, ok) + require.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgUpdateParams.Authority) + require.Equal(t, "cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msgUpdateParams.Params.IssuerCreator) + + createIssuerProposalMessage := weightedProposalMsgs[1] + // tests createIssuerProposalMessage interface: + require.Equal(t, simulation.OpWeightMsgCreateIssuerProposal, createIssuerProposalMessage.AppParamsKey()) + require.Equal(t, simulation.DefaultWeightMsgCreateIssuerProposal, createIssuerProposalMessage.DefaultWeight()) + + createIssuerProposalMsg := createIssuerProposalMessage.MsgSimulatorFn()(r, ctx, accounts) + msgCreateIssuer, ok := createIssuerProposalMsg.(*plasticcredit.MsgCreateIssuer) + require.True(t, ok) + require.Equal(t, sdk.AccAddress(address.Module("gov")).String(), msgCreateIssuer.Creator) + require.Equal(t, "cosmos1tnh2q55v8wyygtt9srz5safamzdengsnqeycj3", msgCreateIssuer.Admin) +} diff --git a/chain/x/plasticcredit/simulation/utils.go b/chain/x/plasticcredit/simulation/utils.go new file mode 100644 index 000000000..b364ccd4d --- /dev/null +++ b/chain/x/plasticcredit/simulation/utils.go @@ -0,0 +1,175 @@ +package simulation + +import ( + "context" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/query" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/keeper" +) + +func createUniqueRandomAbbreviation(ctx context.Context, r *rand.Rand, querier keeper.Querier) string { + for { // Loop until we find a unique abbreviation + abbreviation := createRandomAbbreviation(r) + + // Check if abbreviation is unique + resp, _ := querier.CreditClass(ctx, &plasticcredit.QueryCreditClassRequest{ + CreditClassAbbreviation: abbreviation, + }) + if resp == nil { + return abbreviation + } + } +} + +func createRandomAbbreviation(r *rand.Rand) string { + // Start with a letter + abbreviation := string(rune(simtypes.RandIntBetween(r, 65, 90))) + + length := simtypes.RandIntBetween(r, 2, 5) + for i := 0; i < length-1; i++ { + isNumber := simtypes.RandIntBetween(r, 0, 10) == 1 + if isNumber { + abbreviation += fmt.Sprint(simtypes.RandIntBetween(r, 0, 9)) + } else { + abbreviation += string(rune(simtypes.RandIntBetween(r, 65, 90))) + } + } + + return abbreviation +} + +func createUniqueRandomSerialNumber(ctx context.Context, r *rand.Rand, querier keeper.Querier, abbreviation string) string { + for { // Loop until we find a unique serial number + serialNumber := createRandomSerialNumber(r) + + denom, err := keeper.CreateCreditDenom(abbreviation, serialNumber) + if err != nil { + panic(err) // Should never happen + } + // Check if serial number is unique + resp, _ := querier.CreditCollection(ctx, &plasticcredit.QueryCreditCollectionRequest{ + Denom: denom, + }) + if resp == nil { + return serialNumber + } + } +} + +func createRandomSerialNumber(r *rand.Rand) string { + return simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 1, 256)) +} + +func createRandomName(r *rand.Rand) string { + return simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 2, 64)) +} + +func createRandomDescription(r *rand.Rand) string { + return simtypes.RandStringOfLength(r, simtypes.RandIntBetween(r, 2, 256)) +} + +func getRandomIssuer(ctx context.Context, r *rand.Rand, querier keeper.Querier, ids plasticcredit.IDCounters) (plasticcredit.Issuer, error) { + if ids.NextIssuerId == 0 || ids.NextIssuerId == 1 { + return plasticcredit.Issuer{}, fmt.Errorf("no issuers found") + } + + issuerID := safeRandIntBetween(r, 1, int(ids.NextIssuerId-1)) + + resp, err := querier.Issuer(ctx, &plasticcredit.QueryIssuerRequest{ + IssuerId: uint64(issuerID), + }) + if err != nil { + return plasticcredit.Issuer{}, err + } + + return resp.Issuer, nil +} + +func getRandomApplicant(ctx context.Context, r *rand.Rand, querier keeper.Querier, ids plasticcredit.IDCounters) (plasticcredit.Applicant, error) { + if ids.NextApplicantId == 0 || ids.NextApplicantId == 1 { + return plasticcredit.Applicant{}, fmt.Errorf("no applicants found") + } + + applicantID := safeRandIntBetween(r, 1, int(ids.NextApplicantId-1)) + resp, err := querier.Applicant(ctx, &plasticcredit.QueryApplicantRequest{ + ApplicantId: uint64(applicantID), + }) + if err != nil { + return plasticcredit.Applicant{}, err + } + + return resp.Applicant, nil +} + +func getRandomCreditClass(ctx context.Context, r *rand.Rand, querier keeper.Querier) (plasticcredit.CreditClass, error) { + resp, err := querier.CreditClasses(ctx, &plasticcredit.QueryCreditClassesRequest{ + // We max the return to 25 for now, since this lookup is potentially quite expensive + // TODO: Get better indexes so we can look these up more directly + Pagination: query.PageRequest{ + Limit: 25, + CountTotal: false, + }, + }) + if err != nil { + return plasticcredit.CreditClass{}, err + } + + if len(resp.CreditClasses) == 0 { + return plasticcredit.CreditClass{}, fmt.Errorf("no credit classes found") + } + + return resp.CreditClasses[safeRandIntBetween(r, 0, len(resp.CreditClasses)-1)], nil +} + +func getRandomProject(ctx context.Context, r *rand.Rand, querier keeper.Querier, ids plasticcredit.IDCounters) (plasticcredit.Project, error) { + if ids.NextProjectId == 0 || ids.NextProjectId == 1 { + return plasticcredit.Project{}, fmt.Errorf("no projects found") + } + + projectID := safeRandIntBetween(r, 1, int(ids.NextProjectId-1)) + resp, err := querier.Project(ctx, &plasticcredit.QueryProjectRequest{ + ProjectId: uint64(projectID), + }) + if err != nil { + return plasticcredit.Project{}, err + } + + return resp.Project, nil +} + +func getRandomCreditBalance(ctx context.Context, r *rand.Rand, querier keeper.Querier) (plasticcredit.CreditBalance, error) { + resp, err := querier.CreditBalances(ctx, &plasticcredit.QueryCreditBalancesRequest{ + // We max the return to 25 for now, since this lookup is potentially quite expensive + // TODO: Get better indexes so we can look these up more directly + Pagination: query.PageRequest{ + Limit: 25, + CountTotal: false, + }, + }) + if err != nil { + return plasticcredit.CreditBalance{}, err + } + + if len(resp.CreditBalances) == 0 { + return plasticcredit.CreditBalance{}, fmt.Errorf("no credit balances found") + } + + return resp.CreditBalances[safeRandIntBetween(r, 0, len(resp.CreditBalances)-1)], nil +} + +// safeRandIntBetween returns a random int between min and max +// If max is less than or equal to min, it will return min +// This is to make this kind of code safe: +// resp.CreditClasses[safeRandIntBetween(r, 0, len(resp.CreditClasses)-1)] +func safeRandIntBetween(r *rand.Rand, min, max int) int { + if min >= max { + return min + } + + return simtypes.RandIntBetween(r, min, max) +} diff --git a/chain/x/plasticcredit/tx.pb.go b/chain/x/plasticcredit/tx.pb.go index 472ed2518..23a8bb212 100644 --- a/chain/x/plasticcredit/tx.pb.go +++ b/chain/x/plasticcredit/tx.pb.go @@ -31,7 +31,7 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgUpdateParams struct { - // authority is the address of the governance account. + // authority is the address that controls the module (defaults to x/gov unless overwritten in keeper). Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` // params defines the x/plasitccredit parameters to update. // diff --git a/chain/x/plasticcredit/types.go b/chain/x/plasticcredit/types.go index ae1c04c8c..6ddc68d1d 100644 --- a/chain/x/plasticcredit/types.go +++ b/chain/x/plasticcredit/types.go @@ -37,7 +37,7 @@ func (p Params) Validate() error { if p.IssuerCreator != "" { _, err := sdk.AccAddressFromBech32(p.IssuerCreator) if err != nil { - return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid issuer creator address (%s)", err) + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "params invalid issuer creator address (%s)", err) } } @@ -72,11 +72,11 @@ func (idc IDCounters) Validate() error { func (is Issuer) Validate() error { if is.Id == 0 { - return errors.Wrap(utils.ErrInvalidValue, "id is zero") + return errors.Wrap(utils.ErrInvalidValue, "issuer id is zero") } if !utils.IsBasicValidName(is.Name) { - return errors.Wrap(utils.ErrInvalidValue, "name is invalid") + return errors.Wrapf(utils.ErrInvalidValue, "issuer name is invalid (%s)", is.Name) } if !utils.IsValidDescription(is.Description) { @@ -84,11 +84,11 @@ func (is Issuer) Validate() error { } if is.Admin == "" { - return errors.Wrap(utils.ErrInvalidValue, "admin is empty") + return errors.Wrap(utils.ErrInvalidValue, "issuer admin is empty") } if _, err := sdk.AccAddressFromBech32(is.Admin); err != nil { - return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid admin address (%s)", err) + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid issuer admin address (%s)", err) } return nil @@ -100,11 +100,11 @@ func (is Issuer) AddressHasAuthorization(addr sdk.AccAddress) bool { func (a Applicant) Validate() error { if a.Id == 0 { - return errors.Wrap(utils.ErrInvalidValue, "id is zero") + return errors.Wrap(utils.ErrInvalidValue, "applicant id is zero") } if !utils.IsBasicValidName(a.Name) { - return errors.Wrap(utils.ErrInvalidValue, "name is invalid") + return errors.Wrapf(utils.ErrInvalidValue, "applicant name is invalid (%s)", a.Name) } if !utils.IsValidDescription(a.Description) { @@ -112,11 +112,11 @@ func (a Applicant) Validate() error { } if a.Admin == "" { - return errors.Wrap(utils.ErrInvalidValue, "admin is empty") + return errors.Wrap(utils.ErrInvalidValue, "applicant admin is empty") } if _, err := sdk.AccAddressFromBech32(a.Admin); err != nil { - return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid admin address (%s)", err) + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid applicant admin address (%s)", err) } return nil @@ -130,15 +130,15 @@ var creditClassAbbreviationRegex = regexp.MustCompile(`^[A-Z0-9]{2,5}$`) func (cc CreditClass) Validate() error { if !creditClassAbbreviationRegex.MatchString(cc.Abbreviation) { - return errors.Wrapf(utils.ErrInvalidValue, "abbreviation is invalid, must match %s", creditClassAbbreviationRegex.String()) + return errors.Wrapf(utils.ErrInvalidValue, "credit class abbreviation %q is invalid, must match %s", cc.Abbreviation, creditClassAbbreviationRegex.String()) } if cc.IssuerId == 0 { - return errors.Wrap(utils.ErrInvalidValue, "issuer_id is zero") + return errors.Wrap(utils.ErrInvalidValue, "credit class issuer_id is zero") } if !utils.IsBasicValidName(cc.Name) { - return errors.Wrap(utils.ErrInvalidValue, "name is invalid") + return errors.Wrapf(utils.ErrInvalidValue, "credit class name is invalid (%s)", cc.Name) } return nil @@ -146,23 +146,23 @@ func (cc CreditClass) Validate() error { func (proj Project) Validate() error { if proj.Id == 0 { - return errors.Wrap(utils.ErrInvalidValue, "project_id is zero") + return errors.Wrap(utils.ErrInvalidValue, "project id is zero") } if proj.ApplicantId == 0 { - return errors.Wrap(utils.ErrInvalidValue, "applicant_id is zero") + return errors.Wrap(utils.ErrInvalidValue, "project applicant_id is zero") } if proj.CreditClassAbbreviation == "" { - return errors.Wrap(utils.ErrInvalidValue, "credit_class_abbreviation is empty") + return errors.Wrap(utils.ErrInvalidValue, "project credit_class_abbreviation is empty") } if !utils.IsBasicValidName(proj.Name) { - return errors.Wrap(utils.ErrInvalidValue, "name is invalid") + return errors.Wrapf(utils.ErrInvalidValue, "project name is invalid (%s)", proj.Name) } if _, ok := ProjectStatus_name[int32(proj.Status)]; !ok { - return errors.Wrapf(utils.ErrInvalidValue, "status is invalid %d", proj.Status) + return errors.Wrapf(utils.ErrInvalidValue, "project status is invalid %d", proj.Status) } return nil @@ -170,23 +170,23 @@ func (proj Project) Validate() error { func (cc CreditCollection) Validate() error { if cc.Denom == "" { - return errors.Wrap(utils.ErrInvalidValue, "denom is empty") + return errors.Wrap(utils.ErrInvalidValue, "credit collection denom is empty") } if cc.ProjectId == 0 { - return errors.Wrap(utils.ErrInvalidValue, "project id is empty or zero") + return errors.Wrap(utils.ErrInvalidValue, "credit collection project_id is empty or zero") } if cc.TotalAmount.Active == 0 && cc.TotalAmount.Retired == 0 { - return errors.Wrap(utils.ErrInvalidValue, "cannot have a collection with 0 credits") + return errors.Wrap(utils.ErrInvalidValue, "credit collection cannot have a collection with 0 credits") } return nil } func (cb CreditBalance) Validate() error { if _, err := sdk.AccAddressFromBech32(cb.Owner); err != nil { - return errors.Wrapf(sdkerrors.ErrInvalidAddress, "invalid credit owner address (%s)", err) + return errors.Wrapf(sdkerrors.ErrInvalidAddress, "credit balance invalid credit owner address (%s)", err) } if cb.Denom == "" { - return errors.Wrap(utils.ErrInvalidValue, "denom is empty") + return errors.Wrap(utils.ErrInvalidValue, "credit balance denom is empty") } return nil }