diff --git a/app/app.go b/app/app.go index 589eb2c02..e48cebbc6 100644 --- a/app/app.go +++ b/app/app.go @@ -8,6 +8,10 @@ import ( "os" "path/filepath" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + + sudotypes "github.com/NibiruChain/nibiru/x/sudo/types" + "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" dbm "github.com/cometbft/cometbft-db" @@ -191,7 +195,7 @@ var ( epochstypes.ModuleName: {}, stablecointypes.StableEFModuleAccount: {authtypes.Burner}, - sudo.ModuleName: {}, + sudotypes.ModuleName: {}, common.TreasuryPoolModuleAccount: {}, wasm.ModuleName: {authtypes.Burner}, } @@ -270,7 +274,7 @@ type NibiruApp struct { OracleKeeper oraclekeeper.Keeper StablecoinKeeper stablecoinkeeper.Keeper InflationKeeper inflationkeeper.Keeper - SudoKeeper sudo.Keeper + SudoKeeper keeper.Keeper // WASM keepers WasmKeeper wasm.Keeper diff --git a/app/keepers.go b/app/keepers.go index 60f40e316..a47ef1388 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -3,6 +3,10 @@ package app import ( "path/filepath" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + + sudotypes "github.com/NibiruChain/nibiru/x/sudo/types" + _ "github.com/cosmos/cosmos-sdk/client/docs/statik" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec" @@ -137,7 +141,7 @@ func GetStoreKeys() ( epochstypes.StoreKey, perpv2types.StoreKey, inflationtypes.StoreKey, - sudo.StoreKey, + sudotypes.StoreKey, wasm.StoreKey, ) tkeys = sdk.NewTransientStoreKeys(paramstypes.TStoreKey) @@ -298,8 +302,8 @@ func (app *NibiruApp) InitKeepers( app.AccountKeeper, app.BankKeeper, app.DistrKeeper, app.stakingKeeper, authtypes.FeeCollectorName, ) - app.SudoKeeper = sudo.NewKeeper( - appCodec, keys[sudo.StoreKey], + app.SudoKeeper = keeper.NewKeeper( + appCodec, keys[sudotypes.StoreKey], ) app.EpochsKeeper.SetHooks( @@ -572,7 +576,7 @@ func OrderedModuleNames() []string { oracletypes.ModuleName, perpv2types.ModuleName, inflationtypes.ModuleName, - sudo.ModuleName, + sudotypes.ModuleName, // -------------------------------------------------------------------- // IBC modules diff --git a/x/common/testutil/cli/query.go b/x/common/testutil/cli/query.go index cbc550566..c1062c55e 100644 --- a/x/common/testutil/cli/query.go +++ b/x/common/testutil/cli/query.go @@ -19,7 +19,7 @@ import ( perpv2cli "github.com/NibiruChain/nibiru/x/perp/v2/client/cli" perpv2types "github.com/NibiruChain/nibiru/x/perp/v2/types" sudocli "github.com/NibiruChain/nibiru/x/sudo/cli" - sudotypes "github.com/NibiruChain/nibiru/x/sudo/pb" + sudotypes "github.com/NibiruChain/nibiru/x/sudo/types" ) // ExecQueryOption defines a type which customizes a CLI query operation. diff --git a/x/common/testutil/genesis/sudo_genesis.go b/x/common/testutil/genesis/sudo_genesis.go index 6ca750766..25eb1a5e3 100644 --- a/x/common/testutil/genesis/sudo_genesis.go +++ b/x/common/testutil/genesis/sudo_genesis.go @@ -6,7 +6,7 @@ import ( "github.com/NibiruChain/nibiru/app" "github.com/NibiruChain/nibiru/x/sudo" - sudotypes "github.com/NibiruChain/nibiru/x/sudo/pb" + sudotypes "github.com/NibiruChain/nibiru/x/sudo/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" diff --git a/x/sudo/cli/cli.go b/x/sudo/cli/cli.go index 0d2d41126..c4e3637eb 100644 --- a/x/sudo/cli/cli.go +++ b/x/sudo/cli/cli.go @@ -5,21 +5,21 @@ import ( "os" "strings" + "github.com/NibiruChain/nibiru/x/sudo/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" - - "github.com/NibiruChain/nibiru/x/sudo/pb" ) // GetTxCmd returns a cli command for this module's transactions func GetTxCmd() *cobra.Command { txCmd := &cobra.Command{ - Use: pb.ModuleName, - Short: fmt.Sprintf("x/%s transaction subcommands", pb.ModuleName), + Use: types.ModuleName, + Short: fmt.Sprintf("x/%s transaction subcommands", types.ModuleName), DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, @@ -36,9 +36,9 @@ func GetTxCmd() *cobra.Command { // GetQueryCmd returns a cli command for this module's queries func GetQueryCmd() *cobra.Command { moduleQueryCmd := &cobra.Command{ - Use: pb.ModuleName, + Use: types.ModuleName, Short: fmt.Sprintf( - "Query commands for the x/%s module", pb.ModuleName), + "Query commands for the x/%s module", types.ModuleName), DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, @@ -84,7 +84,7 @@ func CmdEditSudoers() *cobra.Command { return err } - msg := new(pb.MsgEditSudoers) + msg := new(types.MsgEditSudoers) // marshals contents into the proto.Message to which 'msg' points. contents, err := os.ReadFile(args[0]) @@ -123,9 +123,9 @@ func CmdQuerySudoers() *cobra.Command { return err } - queryClient := pb.NewQueryClient(clientCtx) + queryClient := types.NewQueryClient(clientCtx) - req := new(pb.QuerySudoersRequest) + req := new(types.QuerySudoersRequest) resp, err := queryClient.QuerySudoers( cmd.Context(), req, ) diff --git a/x/sudo/cli/cli_test.go b/x/sudo/cli/cli_test.go index 09e6840fc..beaa1509c 100644 --- a/x/sudo/cli/cli_test.go +++ b/x/sudo/cli/cli_test.go @@ -6,11 +6,18 @@ import ( "strings" "testing" + "github.com/NibiruChain/nibiru/x/sudo/types" + "github.com/cosmos/gogoproto/jsonpb" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/crypto" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/NibiruChain/nibiru/app" "github.com/NibiruChain/nibiru/x/common" "github.com/NibiruChain/nibiru/x/common/denoms" @@ -19,12 +26,6 @@ import ( testutilcli "github.com/NibiruChain/nibiru/x/common/testutil/cli" "github.com/NibiruChain/nibiru/x/common/testutil/genesis" "github.com/NibiruChain/nibiru/x/sudo/cli" - "github.com/NibiruChain/nibiru/x/sudo/pb" - - "github.com/cosmos/cosmos-sdk/crypto" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdktestutil "github.com/cosmos/cosmos-sdk/testutil" - sdk "github.com/cosmos/cosmos-sdk/types" ) // ——————————————————————————————————————————————————————————————————— @@ -34,7 +35,7 @@ import ( // MsgEditSudoersPlus is a wrapper struct to extend the default MsgEditSudoers // type with convenience functions type MsgEditSudoersPlus struct { - pb.MsgEditSudoers + types.MsgEditSudoers } // ToJson converts the message into a json string and saves it in a temporary @@ -52,7 +53,7 @@ func (msg MsgEditSudoersPlus) ToJson(t *testing.T) (fileJsonBz []byte, fileName `, msg.Action, strings.Join(msg.Contracts, `", "`), msg.Sender) t.Log("check the unmarshal json → proto") - tempMsg := new(pb.MsgEditSudoers) + tempMsg := new(types.MsgEditSudoers) err := jsonpb.UnmarshalString(msgJsonStr, tempMsg) assert.NoErrorf(t, err, "DEBUG tempMsg: %v\njsonStr: %v", tempMsg, msgJsonStr) @@ -158,7 +159,7 @@ func (s *IntegrationSuite) TestCmdEditSudoers() { var sender sdk.AccAddress = s.root.addr - pbMsg := pb.MsgEditSudoers{ + pbMsg := types.MsgEditSudoers{ Action: "add_contracts", Contracts: []string{contracts[0], contracts[1], contracts[2]}, Sender: sender.String(), @@ -191,7 +192,7 @@ func (s *IntegrationSuite) TestCmdEditSudoers() { s.True(gotContracts.Has(contract)) } - pbMsg = pb.MsgEditSudoers{ + pbMsg = types.MsgEditSudoers{ Action: "remove_contracts", Contracts: []string{contracts[1]}, Sender: sender.String(), @@ -231,7 +232,7 @@ func (s *IntegrationSuite) TestMarshal_EditSudoers() { for _, addr := range addrs[1:] { contracts = append(contracts, addr.String()) } - msg := pb.MsgEditSudoers{ + msg := types.MsgEditSudoers{ Action: "add_contracts", Contracts: contracts, Sender: sender.String(), @@ -243,7 +244,7 @@ func (s *IntegrationSuite) TestMarshal_EditSudoers() { t.Log("check unmarshal file → proto") cdc := genesis.TEST_ENCODING_CONFIG.Marshaler - newMsg := new(pb.MsgEditSudoers) + newMsg := new(types.MsgEditSudoers) err := cdc.UnmarshalJSON(fileJsonBz, newMsg) assert.NoErrorf(t, err, "fileJsonBz: #%v", fileJsonBz) require.NoError(t, newMsg.ValidateBasic(), newMsg.String()) diff --git a/x/sudo/genesis.go b/x/sudo/genesis.go index 7445a14f1..d43690d5b 100644 --- a/x/sudo/genesis.go +++ b/x/sudo/genesis.go @@ -3,11 +3,12 @@ package sudo import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/NibiruChain/nibiru/x/sudo/pb" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + "github.com/NibiruChain/nibiru/x/sudo/types" ) // InitGenesis initializes the module's state from a provided genesis state JSON. -func InitGenesis(ctx sdk.Context, k Keeper, genState pb.GenesisState) { +func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) { if err := genState.Validate(); err != nil { panic(err) } @@ -16,20 +17,20 @@ func InitGenesis(ctx sdk.Context, k Keeper, genState pb.GenesisState) { // ExportGenesis returns the module's exported genesis state. // This fn assumes InitGenesis has already been called. -func ExportGenesis(ctx sdk.Context, k Keeper) *pb.GenesisState { +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { pbSudoers, err := k.Sudoers.Get(ctx) if err != nil { panic(err) } - return &pb.GenesisState{ + return &types.GenesisState{ Sudoers: pbSudoers, } } -func DefaultGenesis() *pb.GenesisState { - return &pb.GenesisState{ - Sudoers: pb.Sudoers{ +func DefaultGenesis() *types.GenesisState { + return &types.GenesisState{ + Sudoers: types.Sudoers{ Root: "", Contracts: []string{}, }, diff --git a/x/sudo/querier.go b/x/sudo/keeper/querier.go similarity index 67% rename from x/sudo/querier.go rename to x/sudo/keeper/querier.go index 99a1af562..d0ebcc623 100644 --- a/x/sudo/querier.go +++ b/x/sudo/keeper/querier.go @@ -1,9 +1,9 @@ -package sudo +package keeper import ( "context" - "github.com/NibiruChain/nibiru/x/sudo/pb" + "github.com/NibiruChain/nibiru/x/sudo/types" sdk "github.com/cosmos/cosmos-sdk/types" "google.golang.org/grpc/codes" @@ -11,12 +11,12 @@ import ( ) // Ensure the interface is properly implemented at compile time -var _ pb.QueryServer = Keeper{} +var _ types.QueryServer = Keeper{} func (k Keeper) QuerySudoers( goCtx context.Context, - req *pb.QuerySudoersRequest, -) (resp *pb.QuerySudoersResponse, err error) { + req *types.QuerySudoersRequest, +) (resp *types.QuerySudoersResponse, err error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } @@ -24,7 +24,7 @@ func (k Keeper) QuerySudoers( ctx := sdk.UnwrapSDKContext(goCtx) sudoers, err := k.Sudoers.Get(ctx) - return &pb.QuerySudoersResponse{ + return &types.QuerySudoersResponse{ Sudoers: sudoers, }, err } diff --git a/x/sudo/sudo.go b/x/sudo/keeper/sudo.go similarity index 76% rename from x/sudo/sudo.go rename to x/sudo/keeper/sudo.go index 4b745d01f..557587600 100644 --- a/x/sudo/sudo.go +++ b/x/sudo/keeper/sudo.go @@ -1,25 +1,21 @@ -package sudo +package keeper import ( "context" "fmt" + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/types" - - "github.com/cosmos/cosmos-sdk/types/errors" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/NibiruChain/collections" - "github.com/cosmos/cosmos-sdk/codec" "github.com/NibiruChain/nibiru/x/common/set" - "github.com/NibiruChain/nibiru/x/sudo/pb" - - sdkerrors "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" + sudotypes "github.com/NibiruChain/nibiru/x/sudo/types" ) type Keeper struct { - Sudoers collections.Item[PbSudoers] + Sudoers collections.Item[sudotypes.Sudoers] } func NewKeeper( @@ -31,41 +27,20 @@ func NewKeeper( } } -var ROOT_ACTIONS = pb.ROOT_ACTIONS -var ROOT_ACTION = pb.ROOT_ACTION - -func NewHandler(k Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { - goCtx := sdk.WrapSDKContext( - ctx.WithEventManager(sdk.NewEventManager()), - ) - switch msg := msg.(type) { - case *pb.MsgEditSudoers: - res, err := k.EditSudoers(goCtx, msg) - return sdk.WrapServiceResult(ctx, res, err) - - default: - errMsg := fmt.Sprintf( - "unrecognized %s message type: %T", pb.ModuleName, msg) - return nil, sdkerrors.Wrap(errors.ErrUnknownRequest, errMsg) - } - } -} - // Ensure the interface is properly implemented at compile time -var _ pb.MsgServer = Keeper{} +var _ sudotypes.MsgServer = Keeper{} // EditSudoers adds or removes sudo contracts from state. func (k Keeper) EditSudoers( - goCtx context.Context, msg *pb.MsgEditSudoers, -) (*pb.MsgEditSudoersResponse, error) { + goCtx context.Context, msg *sudotypes.MsgEditSudoers, +) (*sudotypes.MsgEditSudoersResponse, error) { if err := msg.ValidateBasic(); err != nil { return nil, err } - switch msg.Action { - case ROOT_ACTION.AddContracts: + switch msg.RootAction() { + case sudotypes.AddContracts: return k.AddContracts(goCtx, msg) - case ROOT_ACTION.RemoveContracts: + case sudotypes.RemoveContracts: return k.RemoveContracts(goCtx, msg) default: return nil, fmt.Errorf("invalid action type specified on msg: %s", msg) @@ -85,12 +60,10 @@ func (k Keeper) SenderHasPermission(sender string, root string) error { // Encoder for the Sudoers type // ———————————————————————————————————————————————————————————————————————————— -func SudoersValueEncoder(cdc codec.BinaryCodec) collections.ValueEncoder[pb.Sudoers] { - return collections.ProtoValueEncoder[pb.Sudoers](cdc) +func SudoersValueEncoder(cdc codec.BinaryCodec) collections.ValueEncoder[sudotypes.Sudoers] { + return collections.ProtoValueEncoder[sudotypes.Sudoers](cdc) } -type PbSudoers = pb.Sudoers - type Sudoers struct { Root string `json:"root"` Contracts set.Set[string] `json:"contracts"` @@ -100,21 +73,21 @@ func (sudo Sudoers) String() string { return sudo.ToPb().String() } -func (sudo Sudoers) ToPb() pb.Sudoers { - return pb.Sudoers{ +func (sudo Sudoers) ToPb() sudotypes.Sudoers { + return sudotypes.Sudoers{ Root: sudo.Root, Contracts: sudo.Contracts.ToSlice(), } } -func (sudo Sudoers) FromPb(pbSudoers pb.Sudoers) Sudoers { +func SudoersFromPb(pbSudoers sudotypes.Sudoers) Sudoers { return Sudoers{ Root: pbSudoers.Root, Contracts: set.New[string](pbSudoers.Contracts...), } } -func SudoersToPb(sudo Sudoers) pb.Sudoers { +func SudoersToPb(sudo Sudoers) sudotypes.Sudoers { return sudo.ToPb() } @@ -122,7 +95,7 @@ func SudoersToPb(sudo Sudoers) pb.Sudoers { // AddContracts // ———————————————————————————————————————————————————————————————————————————— -// Sudoers.AddContracts adds contract addresses to the sudoer set. +// AddContracts adds contract addresses to the sudoer set. func (sudo *Sudoers) AddContracts( contracts []string, ) (out set.Set[string], err error) { @@ -136,12 +109,12 @@ func (sudo *Sudoers) AddContracts( return sudo.Contracts, err } -// Keeper.AddContracts executes a MsgEditSudoers message with action type +// AddContracts executes a MsgEditSudoers message with action type // "add_contracts". This adds contract addresses to the sudoer set. func (k Keeper) AddContracts( - goCtx context.Context, msg *pb.MsgEditSudoers, -) (msgResp *pb.MsgEditSudoersResponse, err error) { - if msg.Action != ROOT_ACTION.AddContracts { + goCtx context.Context, msg *sudotypes.MsgEditSudoers, +) (msgResp *sudotypes.MsgEditSudoersResponse, err error) { + if msg.RootAction() != sudotypes.AddContracts { err = fmt.Errorf("invalid action type %s for msg add contracts", msg.Action) return } @@ -152,7 +125,7 @@ func (k Keeper) AddContracts( if err != nil { return } - sudoersBefore := Sudoers{}.FromPb(pbSudoersBefore) + sudoersBefore := SudoersFromPb(pbSudoersBefore) err = k.SenderHasPermission(msg.Sender, sudoersBefore.Root) if err != nil { return @@ -165,8 +138,8 @@ func (k Keeper) AddContracts( } pbSudoers := SudoersToPb(Sudoers{Root: sudoersBefore.Root, Contracts: contracts}) k.Sudoers.Set(ctx, pbSudoers) - msgResp = new(pb.MsgEditSudoersResponse) - return msgResp, ctx.EventManager().EmitTypedEvent(&pb.EventUpdateSudoers{ + msgResp = new(sudotypes.MsgEditSudoersResponse) + return msgResp, ctx.EventManager().EmitTypedEvent(&sudotypes.EventUpdateSudoers{ Sudoers: pbSudoers, Action: msg.Action, }) @@ -177,9 +150,9 @@ func (k Keeper) AddContracts( // ———————————————————————————————————————————————————————————————————————————— func (k Keeper) RemoveContracts( - goCtx context.Context, msg *pb.MsgEditSudoers, -) (msgResp *pb.MsgEditSudoersResponse, err error) { - if msg.Action != ROOT_ACTION.RemoveContracts { + goCtx context.Context, msg *sudotypes.MsgEditSudoers, +) (msgResp *sudotypes.MsgEditSudoersResponse, err error) { + if msg.RootAction() != sudotypes.RemoveContracts { err = fmt.Errorf("invalid action type %s for msg add contracts", msg.Action) return } @@ -194,7 +167,7 @@ func (k Keeper) RemoveContracts( if err != nil { return } - sudoers := Sudoers{}.FromPb(pbSudoers) + sudoers := SudoersFromPb(pbSudoers) err = k.SenderHasPermission(msg.Sender, sudoers.Root) if err != nil { return @@ -205,8 +178,8 @@ func (k Keeper) RemoveContracts( pbSudoers = SudoersToPb(sudoers) k.Sudoers.Set(ctx, pbSudoers) - msgResp = new(pb.MsgEditSudoersResponse) - return msgResp, ctx.EventManager().EmitTypedEvent(&pb.EventUpdateSudoers{ + msgResp = new(sudotypes.MsgEditSudoersResponse) + return msgResp, ctx.EventManager().EmitTypedEvent(&sudotypes.EventUpdateSudoers{ Sudoers: pbSudoers, Action: msg.Action, }) @@ -254,7 +227,7 @@ func (k Keeper) GetSudoContracts(ctx sdk.Context) (contracts []string, err error // SetSudoContracts overwrites the state. This function is a convenience // function for testing with permissioned contracts in other modules.. func (k Keeper) SetSudoContracts(contracts []string, ctx sdk.Context) { - k.Sudoers.Set(ctx, pb.Sudoers{ + k.Sudoers.Set(ctx, sudotypes.Sudoers{ Root: "", Contracts: contracts, }) diff --git a/x/sudo/sudo_test.go b/x/sudo/keeper/sudo_test.go similarity index 87% rename from x/sudo/sudo_test.go rename to x/sudo/keeper/sudo_test.go index 63324834a..c4fc9e351 100644 --- a/x/sudo/sudo_test.go +++ b/x/sudo/keeper/sudo_test.go @@ -1,20 +1,23 @@ -package sudo_test +package keeper_test import ( "testing" "time" - "github.com/NibiruChain/nibiru/app" - "github.com/NibiruChain/nibiru/x/common/set" - "github.com/NibiruChain/nibiru/x/common/testutil" - "github.com/NibiruChain/nibiru/x/common/testutil/testapp" - "github.com/NibiruChain/nibiru/x/sudo" - "github.com/NibiruChain/nibiru/x/sudo/pb" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + + "github.com/NibiruChain/nibiru/x/sudo/types" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/x/common/set" + "github.com/NibiruChain/nibiru/x/common/testutil" + "github.com/NibiruChain/nibiru/x/common/testutil/testapp" + "github.com/NibiruChain/nibiru/x/sudo" ) func init() { @@ -48,7 +51,7 @@ func useNibiAccPrefix() { func TestGenesis(t *testing.T) { for _, testCase := range []struct { name string - genState *pb.GenesisState + genState *types.GenesisState panic bool empty bool }{ @@ -59,8 +62,8 @@ func TestGenesis(t *testing.T) { }, { name: "happy genesis with contracts", - genState: &pb.GenesisState{ - Sudoers: sudo.PbSudoers{ + genState: &types.GenesisState{ + Sudoers: types.Sudoers{ Root: testutil.AccAddress().String(), Contracts: []string{ testutil.AccAddress().String(), @@ -78,8 +81,8 @@ func TestGenesis(t *testing.T) { }, { name: "invalid genesis (panic)", - genState: &pb.GenesisState{ - Sudoers: sudo.PbSudoers{ + genState: &types.GenesisState{ + Sudoers: types.Sudoers{ Root: "root", Contracts: []string{"contract"}, }}, @@ -114,7 +117,7 @@ func TestGenesis(t *testing.T) { require.EqualValues(t, *testCase.genState, *got) // Validate with AppModule - cdc := pb.ModuleCdc + cdc := types.ModuleCdc require.Panics(t, func() { // failing case appModule := sudo.AppModule{} @@ -170,7 +173,7 @@ func TestSudo_AddContracts(t *testing.T) { t.Run(tc.name, func(t *testing.T) { _, _ = setup() root := testutil.AccAddress().String() - sudoers := sudo.Sudoers{ + sudoers := keeper.Sudoers{ Root: root, Contracts: set.New(tc.start...), } @@ -188,32 +191,32 @@ func TestSudo_AddContracts(t *testing.T) { func TestSudo_FromPbSudoers(t *testing.T) { for _, tc := range []struct { name string - in sudo.PbSudoers - out sudo.Sudoers + in types.Sudoers + out keeper.Sudoers }{ { name: "empty", - in: pb.Sudoers{}, - out: sudo.Sudoers{ + in: types.Sudoers{}, + out: keeper.Sudoers{ Root: "", Contracts: set.Set[string]{}, }, }, { name: "happy", - in: pb.Sudoers{Root: "root", Contracts: []string{"contractA", "contractB"}}, - out: sudo.Sudoers{ + in: types.Sudoers{Root: "root", Contracts: []string{"contractA", "contractB"}}, + out: keeper.Sudoers{ Root: "root", Contracts: set.New[string]("contractA", "contractB"), }, }, } { t.Run(tc.name, func(t *testing.T) { - out := sudo.Sudoers{}.FromPb(tc.in) + out := keeper.SudoersFromPb(tc.in) assert.EqualValues(t, tc.out.Contracts, out.Contracts) assert.EqualValues(t, tc.out.Root, out.Root) - pbSudoers := sudo.SudoersToPb(out) + pbSudoers := keeper.SudoersToPb(out) for _, contract := range tc.in.Contracts { assert.True(t, set.New(pbSudoers.Contracts...).Has(contract)) } @@ -232,7 +235,7 @@ func TestKeeper_AddContracts(t *testing.T) { testCases := []struct { name string contractsBefore []string - msg *pb.MsgEditSudoers + msg *types.MsgEditSudoers contractsAfter []string shouldFail bool }{ @@ -241,8 +244,8 @@ func TestKeeper_AddContracts(t *testing.T) { contractsBefore: []string{ exampleAddrs[0], }, - msg: &pb.MsgEditSudoers{ - Action: pb.ROOT_ACTION.AddContracts, + msg: &types.MsgEditSudoers{ + Action: string(types.AddContracts), Contracts: []string{ exampleAddrs[1], exampleAddrs[2], @@ -261,8 +264,8 @@ func TestKeeper_AddContracts(t *testing.T) { contractsBefore: []string{ exampleAddrs[0], }, - msg: &pb.MsgEditSudoers{ - Action: pb.ROOT_ACTION.AddContracts, + msg: &types.MsgEditSudoers{ + Action: string(types.AddContracts), Contracts: []string{ exampleAddrs[1], "rotten address", @@ -278,7 +281,7 @@ func TestKeeper_AddContracts(t *testing.T) { contractsBefore: []string{ exampleAddrs[0], }, - msg: &pb.MsgEditSudoers{ + msg: &types.MsgEditSudoers{ Action: "not an action type", Sender: root, }, @@ -290,8 +293,8 @@ func TestKeeper_AddContracts(t *testing.T) { contractsBefore: []string{ exampleAddrs[0], }, - msg: &pb.MsgEditSudoers{ - Action: pb.ROOT_ACTION.AddContracts, + msg: &types.MsgEditSudoers{ + Action: string(types.AddContracts), Sender: exampleAddrs[1], Contracts: []string{ exampleAddrs[1], @@ -313,7 +316,7 @@ func TestKeeper_AddContracts(t *testing.T) { k := nibiru.SudoKeeper t.Log("Set starting contracts state") - stateBefore := pb.Sudoers{ + stateBefore := types.Sudoers{ Root: root, Contracts: tc.contractsBefore, } @@ -324,8 +327,7 @@ func TestKeeper_AddContracts(t *testing.T) { t.Log("Execute message") // Check via message handler directly - handler := sudo.NewHandler(k) - res, err := handler(ctx, tc.msg) + res, err := k.EditSudoers(sdk.WrapSDKContext(ctx), tc.msg) // Check via Keeper res2, err2 := k.AddContracts(sdk.WrapSDKContext(ctx), tc.msg) if tc.shouldFail { @@ -361,15 +363,6 @@ func (dm *DummyMsg) Reset() {} func (dm *DummyMsg) ProtoMessage() {} func (dm *DummyMsg) String() string { return "dummy" } -func TestUnrecognizedHandlerMessage(t *testing.T) { - handler := sudo.NewHandler(sudo.Keeper{}) - _, ctx := setup() - msg := new(DummyMsg) - _, err := handler(ctx, msg) - require.Error(t, err) - require.Contains(t, err.Error(), "unrecognized") -} - func TestKeeper_RemoveContracts(t *testing.T) { root := "nibi1ggpg3vluy09qmfkgwsgkumhmmv2z44rdafn6qa" // root := "nibi1ggpg3vluy09qmfkgwsgkumhmmv2z44rd2vhrfw" @@ -382,7 +375,7 @@ func TestKeeper_RemoveContracts(t *testing.T) { for _, tc := range []struct { name string contractsBefore []string - msg *pb.MsgEditSudoers + msg *types.MsgEditSudoers contractsAfter []string shouldFail bool }{ @@ -393,8 +386,8 @@ func TestKeeper_RemoveContracts(t *testing.T) { exampleAddrs[1], exampleAddrs[2], }, - msg: &pb.MsgEditSudoers{ - Action: pb.ROOT_ACTION.RemoveContracts, + msg: &types.MsgEditSudoers{ + Action: string(types.RemoveContracts), Contracts: []string{ exampleAddrs[1], exampleAddrs[2], @@ -411,7 +404,7 @@ func TestKeeper_RemoveContracts(t *testing.T) { contractsBefore: []string{ exampleAddrs[0], }, - msg: &pb.MsgEditSudoers{ + msg: &types.MsgEditSudoers{ Action: "not an action type", Sender: root, }, @@ -424,8 +417,8 @@ func TestKeeper_RemoveContracts(t *testing.T) { exampleAddrs[0], exampleAddrs[2], }, - msg: &pb.MsgEditSudoers{ - Action: pb.ROOT_ACTION.RemoveContracts, + msg: &types.MsgEditSudoers{ + Action: string(types.RemoveContracts), Contracts: []string{ exampleAddrs[1], }, @@ -442,7 +435,7 @@ func TestKeeper_RemoveContracts(t *testing.T) { k := nibiru.SudoKeeper t.Log("Set starting contracts state") - stateBefore := pb.Sudoers{ + stateBefore := types.Sudoers{ Root: root, Contracts: tc.contractsBefore, } @@ -453,8 +446,7 @@ func TestKeeper_RemoveContracts(t *testing.T) { t.Log("Execute message") // Check via message handler directly - handler := sudo.NewHandler(k) - res, err := handler(ctx, tc.msg) + res, err := k.EditSudoers(ctx, tc.msg) // Check via Keeper res2, err2 := k.RemoveContracts(sdk.WrapSDKContext(ctx), tc.msg) if tc.shouldFail { @@ -481,11 +473,11 @@ func TestKeeper_RemoveContracts(t *testing.T) { func TestQuerySudoers(t *testing.T) { for _, tc := range []struct { name string - state pb.Sudoers + state types.Sudoers }{ { name: "happy 1", - state: pb.Sudoers{ + state: types.Sudoers{ Root: "alice", Contracts: []string{"contractA", "contractB"}, }, @@ -493,7 +485,7 @@ func TestQuerySudoers(t *testing.T) { { name: "happy 2 (empty)", - state: pb.Sudoers{ + state: types.Sudoers{ Root: "", Contracts: []string(nil), }, @@ -501,7 +493,7 @@ func TestQuerySudoers(t *testing.T) { { name: "happy 3", - state: pb.Sudoers{ + state: types.Sudoers{ Root: "", Contracts: []string{"boop", "blap"}, }, @@ -512,7 +504,7 @@ func TestQuerySudoers(t *testing.T) { nibiru.SudoKeeper.Sudoers.Set(ctx, tc.state) - req := new(pb.QuerySudoersRequest) + req := new(types.QuerySudoersRequest) resp, err := nibiru.SudoKeeper.QuerySudoers( sdk.WrapSDKContext(ctx), req, ) @@ -525,7 +517,7 @@ func TestQuerySudoers(t *testing.T) { t.Run("nil request should error", func(t *testing.T) { nibiru, ctx := setup() - var req *pb.QuerySudoersRequest = nil + var req *types.QuerySudoersRequest = nil _, err := nibiru.SudoKeeper.QuerySudoers( sdk.WrapSDKContext(ctx), req, ) diff --git a/x/sudo/module.go b/x/sudo/module.go index 41102391d..7ad9795db 100644 --- a/x/sudo/module.go +++ b/x/sudo/module.go @@ -11,20 +11,18 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/gorilla/mux" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" "github.com/NibiruChain/nibiru/x/sudo/cli" - "github.com/NibiruChain/nibiru/x/sudo/pb" + sudokeeper "github.com/NibiruChain/nibiru/x/sudo/keeper" + "github.com/NibiruChain/nibiru/x/sudo/types" ) // Ensure the interface is properly implemented at compile time var ( - _ module.AppModule = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} - ModuleName = pb.ModuleName - StoreKey = pb.StoreKey + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} ) // ---------------------------------------------------------------------------- @@ -40,20 +38,16 @@ func NewAppModuleBasic(binaryCodec codec.BinaryCodec) AppModuleBasic { } func (AppModuleBasic) Name() string { - return pb.ModuleName + return types.ModuleName } // RegisterInterfaces registers interfaces and implementations of the perp module. func (AppModuleBasic) RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) { - pb.RegisterInterfaces(interfaceRegistry) -} - -func (AppModuleBasic) RegisterCodec(aminoCodec *codec.LegacyAmino) { - pb.RegisterCodec(aminoCodec) + types.RegisterInterfaces(interfaceRegistry) } func (AppModuleBasic) RegisterLegacyAminoCodec(aminoCodec *codec.LegacyAmino) { - pb.RegisterCodec(aminoCodec) + types.RegisterCodec(aminoCodec) } // DefaultGenesis returns default genesis state as raw bytes for the module. @@ -63,24 +57,20 @@ func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { // ValidateGenesis performs genesis state validation for the capability module. func (AppModuleBasic) ValidateGenesis( - cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage, + cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage, ) error { - var genState pb.GenesisState + var genState types.GenesisState if err := cdc.UnmarshalJSON(bz, &genState); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", pb.ModuleName, err) + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) } return genState.Validate() } -// RegisterRESTRoutes registers the capability module's REST service handlers. -func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { -} - // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module. func (AppModuleBasic) RegisterGRPCGatewayRoutes( clientCtx client.Context, mux *runtime.ServeMux, ) { - if err := pb.RegisterQueryHandlerClient(context.Background(), mux, pb.NewQueryClient(clientCtx)); err != nil { + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { panic(err) } } @@ -103,12 +93,12 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { type AppModule struct { AppModuleBasic - keeper Keeper + keeper sudokeeper.Keeper } func NewAppModule( cdc codec.Codec, - keeper Keeper, + keeper sudokeeper.Keeper, ) AppModule { return AppModule{ AppModuleBasic: NewAppModuleBasic(cdc), @@ -121,14 +111,11 @@ func (am AppModule) Name() string { return am.AppModuleBasic.Name() } -// QuerierRoute returns the capability module's query routing key. -func (AppModule) QuerierRoute() string { return pb.QuerierRoute } - // RegisterServices registers a GRPC query service to respond to the // module-specific GRPC queries. func (am AppModule) RegisterServices(cfg module.Configurator) { - pb.RegisterQueryServer(cfg.QueryServer(), am.keeper) - pb.RegisterMsgServer(cfg.MsgServer(), am.keeper) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) } // RegisterInvariants registers the capability module's invariants. @@ -138,7 +125,7 @@ func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} // no validator updates. func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage, ) []abci.ValidatorUpdate { - var genState pb.GenesisState + var genState types.GenesisState // Initialize global index to index in genesis state cdc.MustUnmarshalJSON(gs, &genState) @@ -161,6 +148,6 @@ func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} // EndBlock executes all ABCI EndBlock logic respective to the capability module. It // returns no validator updates. -func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { +func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { return []abci.ValidatorUpdate{} } diff --git a/x/sudo/pb/actions.go b/x/sudo/pb/actions.go deleted file mode 100644 index 3893e9e5e..000000000 --- a/x/sudo/pb/actions.go +++ /dev/null @@ -1,18 +0,0 @@ -package pb - -import "github.com/NibiruChain/nibiru/x/common/set" - -// ROOT_ACTION is an enum-like struct for each available action type. -var ROOT_ACTION = struct { - AddContracts string - RemoveContracts string -}{ - AddContracts: "add_contracts", - RemoveContracts: "remove_contracts", -} - -// ROOT_ACTIONS set[string]: The set of all root actions. -var ROOT_ACTIONS = set.New( - ROOT_ACTION.AddContracts, - ROOT_ACTION.RemoveContracts, -) diff --git a/x/sudo/types/actions.go b/x/sudo/types/actions.go new file mode 100644 index 000000000..9d838bb8f --- /dev/null +++ b/x/sudo/types/actions.go @@ -0,0 +1,16 @@ +package types + +import "github.com/NibiruChain/nibiru/x/common/set" + +type RootAction string + +const ( + AddContracts RootAction = "add_contracts" + RemoveContracts RootAction = "remove_contracts" +) + +// RootActions set[string]: The set of all root actions. +var RootActions = set.New[RootAction]( + AddContracts, + RemoveContracts, +) diff --git a/x/sudo/pb/codec.go b/x/sudo/types/codec.go similarity index 97% rename from x/sudo/pb/codec.go rename to x/sudo/types/codec.go index 9e0081502..b939e5f64 100644 --- a/x/sudo/pb/codec.go +++ b/x/sudo/types/codec.go @@ -1,4 +1,4 @@ -package pb +package types import ( "github.com/cosmos/cosmos-sdk/codec" diff --git a/x/sudo/pb/event.pb.go b/x/sudo/types/event.pb.go similarity index 99% rename from x/sudo/pb/event.pb.go rename to x/sudo/types/event.pb.go index d7e8cd670..7da3259ee 100644 --- a/x/sudo/pb/event.pb.go +++ b/x/sudo/types/event.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. // source: nibiru/sudo/v1/event.proto -package pb +package types import ( fmt "fmt" diff --git a/x/sudo/pb/msgs.go b/x/sudo/types/msgs.go similarity index 61% rename from x/sudo/pb/msgs.go rename to x/sudo/types/msgs.go index d1840648b..ec8388780 100644 --- a/x/sudo/pb/msgs.go +++ b/x/sudo/types/msgs.go @@ -1,4 +1,4 @@ -package pb +package types import ( fmt "fmt" @@ -16,16 +16,11 @@ var ( // StoreKey defines the primary module store key. StoreKey = ModuleName - MemStoreKey = "mem_" + ModuleName - // RouterKey is the message route for transactions. RouterKey = ModuleName - - // QuerierRoute defines the module's query routing key. - QuerierRoute = ModuleName ) -func (gen GenesisState) Validate() error { +func (gen *GenesisState) Validate() error { if gen.Sudoers.Contracts == nil { return fmt.Errorf("nil contract state must be []string") } else if err := gen.Sudoers.Validate(); err != nil { @@ -36,10 +31,10 @@ func (gen GenesisState) Validate() error { // MsgEditSudoers -func (m MsgEditSudoers) Route() string { return RouterKey } -func (m MsgEditSudoers) Type() string { return "msg_edit_sudoers" } +func (m *MsgEditSudoers) Route() string { return RouterKey } +func (m *MsgEditSudoers) Type() string { return "msg_edit_sudoers" } -func (m MsgEditSudoers) ValidateBasic() error { +func (m *MsgEditSudoers) ValidateBasic() error { if _, err := sdk.AccAddressFromBech32(m.Sender); err != nil { return err } @@ -50,24 +45,28 @@ func (m MsgEditSudoers) ValidateBasic() error { } } - if !ROOT_ACTIONS.Has(m.Action) { + if !RootActions.Has(m.RootAction()) { return fmt.Errorf( "invalid action type %s, expected one of %s", - m.Action, ROOT_ACTIONS.ToSlice(), + m.Action, RootActions.ToSlice(), ) } return nil } -func (m MsgEditSudoers) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +func (m *MsgEditSudoers) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(m)) } -func (m MsgEditSudoers) GetSigners() []sdk.AccAddress { +func (m *MsgEditSudoers) GetSigners() []sdk.AccAddress { signer, err := sdk.AccAddressFromBech32(m.Sender) if err != nil { panic(err) } return []sdk.AccAddress{signer} } + +func (m *MsgEditSudoers) RootAction() RootAction { + return RootAction(m.Action) +} diff --git a/x/sudo/pb/query.pb.go b/x/sudo/types/query.pb.go similarity index 99% rename from x/sudo/pb/query.pb.go rename to x/sudo/types/query.pb.go index 77a5c1c83..5440e39b4 100644 --- a/x/sudo/pb/query.pb.go +++ b/x/sudo/types/query.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. // source: nibiru/sudo/v1/query.proto -package pb +package types import ( context "context" diff --git a/x/sudo/pb/query.pb.gw.go b/x/sudo/types/query.pb.gw.go similarity index 99% rename from x/sudo/pb/query.pb.gw.go rename to x/sudo/types/query.pb.gw.go index e78bda033..ef9f305e6 100644 --- a/x/sudo/pb/query.pb.gw.go +++ b/x/sudo/types/query.pb.gw.go @@ -6,7 +6,7 @@ Package pb is a reverse proxy. It translates gRPC into RESTful JSON APIs. */ -package pb +package types import ( "context" diff --git a/x/sudo/pb/state.go b/x/sudo/types/state.go similarity index 97% rename from x/sudo/pb/state.go rename to x/sudo/types/state.go index 745725d7e..426fd2103 100644 --- a/x/sudo/pb/state.go +++ b/x/sudo/types/state.go @@ -1,4 +1,4 @@ -package pb +package types import ( "encoding/json" diff --git a/x/sudo/pb/state.pb.go b/x/sudo/types/state.pb.go similarity index 99% rename from x/sudo/pb/state.pb.go rename to x/sudo/types/state.pb.go index f92c8a280..b9305290e 100644 --- a/x/sudo/pb/state.pb.go +++ b/x/sudo/types/state.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. // source: nibiru/sudo/v1/state.proto -package pb +package types import ( fmt "fmt" diff --git a/x/sudo/pb/tx.pb.go b/x/sudo/types/tx.pb.go similarity index 99% rename from x/sudo/pb/tx.pb.go rename to x/sudo/types/tx.pb.go index 7b2d03042..86179c98f 100644 --- a/x/sudo/pb/tx.pb.go +++ b/x/sudo/types/tx.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. // source: nibiru/sudo/v1/tx.proto -package pb +package types import ( context "context" diff --git a/x/sudo/pb/tx.pb.gw.go b/x/sudo/types/tx.pb.gw.go similarity index 99% rename from x/sudo/pb/tx.pb.gw.go rename to x/sudo/types/tx.pb.gw.go index b94a33ae1..45ec6493a 100644 --- a/x/sudo/pb/tx.pb.gw.go +++ b/x/sudo/types/tx.pb.gw.go @@ -6,7 +6,7 @@ Package pb is a reverse proxy. It translates gRPC into RESTful JSON APIs. */ -package pb +package types import ( "context" diff --git a/x/wasm/binding/exec.go b/x/wasm/binding/exec.go index a9347b2b7..3bd78fb3f 100644 --- a/x/wasm/binding/exec.go +++ b/x/wasm/binding/exec.go @@ -3,6 +3,8 @@ package binding import ( "encoding/json" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + sdkerrors "cosmossdk.io/errors" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmvmtypes "github.com/CosmWasm/wasmvm/types" @@ -10,7 +12,6 @@ import ( oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" perpv2keeper "github.com/NibiruChain/nibiru/x/perp/v2/keeper" - "github.com/NibiruChain/nibiru/x/sudo" "github.com/NibiruChain/nibiru/x/wasm/binding/cw_struct" ) @@ -21,7 +22,7 @@ var _ wasmkeeper.Messenger = (*CustomWasmExecutor)(nil) type CustomWasmExecutor struct { Wasm wasmkeeper.Messenger Perp ExecutorPerp - Sudo sudo.Keeper + Sudo keeper.Keeper Oracle ExecutorOracle } @@ -136,7 +137,7 @@ func (messenger *CustomWasmExecutor) DispatchMsg( func CustomExecuteMsgHandler( perpv2 perpv2keeper.Keeper, - sudoKeeper sudo.Keeper, + sudoKeeper keeper.Keeper, oracleKeeper oraclekeeper.Keeper, ) func(wasmkeeper.Messenger) wasmkeeper.Messenger { return func(originalWasmMessenger wasmkeeper.Messenger) wasmkeeper.Messenger { diff --git a/x/wasm/binding/wasm.go b/x/wasm/binding/wasm.go index d3882b997..46bc065b6 100644 --- a/x/wasm/binding/wasm.go +++ b/x/wasm/binding/wasm.go @@ -4,14 +4,15 @@ import ( "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/NibiruChain/nibiru/x/sudo/keeper" + oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" perpv2keeper "github.com/NibiruChain/nibiru/x/perp/v2/keeper" - "github.com/NibiruChain/nibiru/x/sudo" ) func RegisterWasmOptions( perpv2 perpv2keeper.Keeper, - sudoKeeper sudo.Keeper, + sudoKeeper keeper.Keeper, oracleKeeper oraclekeeper.Keeper, ) []wasm.Option { wasmQueryPlugin := NewQueryPlugin(perpv2)