diff --git a/x/projects/keeper/project.go b/x/projects/keeper/project.go index 5515bbd481..ea9ff53724 100644 --- a/x/projects/keeper/project.go +++ b/x/projects/keeper/project.go @@ -135,3 +135,7 @@ func (k Keeper) SetProjectPolicy(ctx sdk.Context, projectIDs []string, policy *t return nil } + +func (k Keeper) GetAllProjectsForSubscription(ctx sdk.Context, subscription string) []string { + return k.projectsFS.GetAllEntryIndicesWithPrefix(ctx, subscription) +} diff --git a/x/subscription/client/cli/query_list_projects.go b/x/subscription/client/cli/query_list_projects.go index fec1b04875..76ae9f21c7 100644 --- a/x/subscription/client/cli/query_list_projects.go +++ b/x/subscription/client/cli/query_list_projects.go @@ -27,7 +27,6 @@ func CmdListProjects() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryListProjectsRequest{ - Subscription: reqSubscription, } diff --git a/x/subscription/keeper/grpc_query_list_projects.go b/x/subscription/keeper/grpc_query_list_projects.go index c2121cf5a0..3cfb02f780 100644 --- a/x/subscription/keeper/grpc_query_list_projects.go +++ b/x/subscription/keeper/grpc_query_list_projects.go @@ -4,6 +4,8 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/lavanet/lava/utils" "github.com/lavanet/lava/x/subscription/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -16,8 +18,14 @@ func (k Keeper) ListProjects(goCtx context.Context, req *types.QueryListProjects ctx := sdk.UnwrapSDKContext(goCtx) - // TODO: implement logic - _ = ctx + _, found := k.GetSubscription(ctx, req.Subscription) + if !found { + return nil, utils.LavaFormatWarning("subscription not found", sdkerrors.ErrKeyNotFound, + utils.Attribute{Key: "subscription", Value: req.Subscription}, + ) + } + + projects := k.projectsKeeper.GetAllProjectsForSubscription(ctx, req.Subscription) - return &types.QueryListProjectsResponse{}, nil + return &types.QueryListProjectsResponse{Projects: projects}, nil } diff --git a/x/subscription/keeper/subscription_test.go b/x/subscription/keeper/subscription_test.go index b4fd149aea..77cf49c6d6 100644 --- a/x/subscription/keeper/subscription_test.go +++ b/x/subscription/keeper/subscription_test.go @@ -93,6 +93,7 @@ type testStruct struct { _ctx context.Context ctx sdk.Context keepers *keepertest.Keepers + servers *keepertest.Servers plans []planstypes.Plan } @@ -118,7 +119,7 @@ func (ts *testStruct) expireSubscription(sub types.Subscription) types.Subscript } func setupTestStruct(t *testing.T, numPlans int) testStruct { - _, keepers, _ctx := keepertest.InitAllKeepers(t) + servers, keepers, _ctx := keepertest.InitAllKeepers(t) _ctx = keepertest.AdvanceEpoch(_ctx, keepers) ctx := sdk.UnwrapSDKContext(_ctx) @@ -130,6 +131,7 @@ func setupTestStruct(t *testing.T, numPlans int) testStruct { ctx: ctx, keepers: keepers, plans: plans, + servers: servers, } return ts @@ -620,3 +622,65 @@ func TestAddProjectToSubscription(t *testing.T) { }) } } + +func TestGetProjectsForSubscription(t *testing.T) { + ts := setupTestStruct(t, 1) + plan := ts.plans[0] + + subAcc1 := common.CreateNewAccount(ts._ctx, *ts.keepers, 10000).Addr.String() + subAcc2 := common.CreateNewAccount(ts._ctx, *ts.keepers, 10000).Addr.String() + + // buy two subscriptions + _, err := ts.servers.SubscriptionServer.Buy(ts._ctx, &types.MsgBuy{ + Creator: subAcc1, + Consumer: subAcc1, + Index: plan.Index, + Duration: 1, + }) + require.Nil(t, err) + + _, err = ts.servers.SubscriptionServer.Buy(ts._ctx, &types.MsgBuy{ + Creator: subAcc2, + Consumer: subAcc2, + Index: plan.Index, + Duration: 1, + }) + require.Nil(t, err) + + // add two projects to the first subscription + projData1 := projectstypes.ProjectData{ + Name: "proj1", + Enabled: true, + Policy: &plan.PlanPolicy, + } + _, err = ts.servers.SubscriptionServer.AddProject(ts._ctx, &types.MsgAddProject{ + Creator: subAcc1, + ProjectData: projData1, + }) + require.Nil(t, err) + + projData2 := projectstypes.ProjectData{ + Name: "proj2", + Enabled: false, + Policy: &plan.PlanPolicy, + } + _, err = ts.servers.SubscriptionServer.AddProject(ts._ctx, &types.MsgAddProject{ + Creator: subAcc1, + ProjectData: projData2, + }) + require.Nil(t, err) + + res1, err := ts.keepers.Subscription.ListProjects(ts._ctx, &types.QueryListProjectsRequest{ + Subscription: subAcc1, + }) + require.Nil(t, err) + + res2, err := ts.keepers.Subscription.ListProjects(ts._ctx, &types.QueryListProjectsRequest{ + Subscription: subAcc2, + }) + require.Nil(t, err) + + // check the number of projects are as expected (+1 because there's an auto-generated admin project) + require.Equal(t, 3, len(res1.Projects)) + require.Equal(t, 1, len(res2.Projects)) +} diff --git a/x/subscription/types/expected_keepers.go b/x/subscription/types/expected_keepers.go index aac5b546e5..d690c14731 100644 --- a/x/subscription/types/expected_keepers.go +++ b/x/subscription/types/expected_keepers.go @@ -32,6 +32,7 @@ type ProjectsKeeper interface { CreateProject(ctx sdk.Context, subscriptionAddress string, projectData projectstypes.ProjectData, plan planstypes.Plan) error DeleteProject(ctx sdk.Context, index string) error SnapshotSubscriptionProjects(ctx sdk.Context, subscriptionAddr string) + GetAllProjectsForSubscription(ctx sdk.Context, subscription string) []string // Methods imported from projectskeeper should be defined here }