Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement registered reactions pagination #476

Merged
merged 16 commits into from
Jun 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
- Added the new `x/subspaces` module ([#392](https://github.com/desmos-labs/desmos/issues/392))
- Added the ability to paginate the relationships of a profile ([#467](https://github.com/desmos-labs/desmos/issues/467))
- Added the ability to edit whether users can comment on a post or not ([#446](https://github.com/desmos-labs/desmos/issues/446))

- Added the ability to paginate the registered reactions ([#471](https://github.com/desmos-labs/desmos/issues/471))

# Version 0.16.3
## Changes
Expand Down
11 changes: 10 additions & 1 deletion proto/desmos/posts/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,22 @@ message QueryPollAnswersResponse {

// QueryRegisteredReactionsRequest is the request type for the
// Query/RegisteredReactions RPC method.
message QueryRegisteredReactionsRequest {}
message QueryRegisteredReactionsRequest {

// subspace to query the registered reactions for
string subspace = 1;

// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 2;
}

// QueryRegisteredReactionsResponse is the response type for the
// Query/RegisteredReactions RPC method
message QueryRegisteredReactionsResponse {
repeated desmos.posts.v1beta1.RegisteredReaction registered_reactions = 1
[ (gogoproto.nullable) = false ];

cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// ___________________________________________________________________________________________________________________
Expand Down
61 changes: 60 additions & 1 deletion x/staging/posts/client/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
Expand Down Expand Up @@ -53,6 +54,12 @@ func (s *IntegrationTestSuite) SetupSuite() {
"https://example.com/reaction.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":smile-jpg:",
"https://smile.jpg",
"5e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
}
postsData.Posts = []types.Post{
{
Expand Down Expand Up @@ -375,7 +382,7 @@ func (s *IntegrationTestSuite) TestCmdQueryRegisteredReactions() {
expectedOutput types.QueryRegisteredReactionsResponse
}{
{
name: "data is returned properly",
name: "data without subspace and pagination is returned properly",
args: []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
expectErr: false,
expectedOutput: types.QueryRegisteredReactionsResponse{
Expand All @@ -386,6 +393,58 @@ func (s *IntegrationTestSuite) TestCmdQueryRegisteredReactions() {
"https://example.com/reaction.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":smile-jpg:",
"https://smile.jpg",
"5e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
},
Pagination: &query.PageResponse{
NextKey: nil,
Total: 0,
},
},
},
{
name: "data with subspace is returned properly",
args: []string{"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e", fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
expectErr: false,
expectedOutput: types.QueryRegisteredReactionsResponse{
RegisteredReactions: []types.RegisteredReaction{
types.NewRegisteredReaction(
"cosmos1lhhkerae9cu3fa442vt50t32grlajun5lmrv3g",
":reaction:",
"https://example.com/reaction.jpg",
"4e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
},
Pagination: &query.PageResponse{
NextKey: nil,
Total: 0,
},
},
},
{
name: "data with pagination is returned properly",
args: []string{
fmt.Sprintf("--%s=%d", flags.FlagPage, 2),
fmt.Sprintf("--%s=%d", flags.FlagLimit, 1),
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
},
expectErr: false,
expectedOutput: types.QueryRegisteredReactionsResponse{
RegisteredReactions: []types.RegisteredReaction{
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":smile-jpg:",
"https://smile.jpg",
"5e188d9c17150037d5199bbdb91ae1eb2a78a15aca04cb35530cccb81494b36e",
),
},
Pagination: &query.PageResponse{
NextKey: nil,
Total: 0,
},
},
},
Expand Down
19 changes: 15 additions & 4 deletions x/staging/posts/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,27 @@ func GetCmdQueryPollAnswers() *cobra.Command {
// GetCmdQueryRegisteredReactions returns the command allowing to query the registered reactions
func GetCmdQueryRegisteredReactions() *cobra.Command {
cmd := &cobra.Command{
Use: "registered-reactions",
Short: "Retrieve tha poll answers of the post with given id",
Args: cobra.ExactArgs(0),
Use: "registered-reactions [[subspace]]",
Short: "Retrieve tha registered reactions with optional subspace",
Args: cobra.RangeArgs(0, 1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := types.NewQueryClient(clientCtx)

res, err := queryClient.RegisteredReactions(context.Background(), &types.QueryRegisteredReactionsRequest{})
var subspace string
if len(args) == 1 {
subspace = args[0]
}

pageReq, err := client.ReadPageRequest(cmd.Flags())
if err != nil {
return err
}

res, err := queryClient.RegisteredReactions(context.Background(), &types.QueryRegisteredReactionsRequest{Subspace: subspace, Pagination: pageReq})
if err != nil {
return err
}
Expand All @@ -226,6 +236,7 @@ func GetCmdQueryRegisteredReactions() *cobra.Command {
}

flags.AddQueryFlagsToCmd(cmd)
flags.AddPaginationFlagsToCmd(cmd, types.QueryRegisteredReactions)

return cmd
}
Expand Down
22 changes: 19 additions & 3 deletions x/staging/posts/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,27 @@ func (k Keeper) PollAnswers(goCtx context.Context, req *types.QueryPollAnswersRe
return &types.QueryPollAnswersResponse{PostId: req.PostId, Answers: pollAnswers}, nil
}

func (k Keeper) RegisteredReactions(goCtx context.Context, _ *types.QueryRegisteredReactionsRequest) (*types.QueryRegisteredReactionsResponse, error) {
func (k Keeper) RegisteredReactions(goCtx context.Context, req *types.QueryRegisteredReactionsRequest) (*types.QueryRegisteredReactionsResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

reactions := k.GetRegisteredReactions(ctx)
return &types.QueryRegisteredReactionsResponse{RegisteredReactions: reactions}, nil
var reactions []types.RegisteredReaction

store := ctx.KVStore(k.storeKey)
reactionsStore := prefix.NewStore(store, types.RegisteredReactionsPrefix(req.Subspace))

pageRes, err := query.FilteredPaginate(reactionsStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) {
var reaction types.RegisteredReaction
k.cdc.UnmarshalBinaryBare(value, &reaction)
if accumulate {
reactions = append(reactions, reaction)
}
return true, nil
})

if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
return &types.QueryRegisteredReactionsResponse{RegisteredReactions: reactions, Pagination: pageRes}, nil
}

// Reports implements the Query/Reports gRPC method
Expand Down
88 changes: 88 additions & 0 deletions x/staging/posts/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package keeper_test

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/desmos-labs/desmos/x/staging/posts/types"
)

func (suite *KeeperTestSuite) Test_RegisteredReactions() {
usecases := []struct {
name string
storedReactions []types.RegisteredReaction
req *types.QueryRegisteredReactionsRequest
expLen int
}{
{
name: "query registered reactions without subspace and pagination",
storedReactions: []types.RegisteredReaction{
types.NewRegisteredReaction(
"creator",
":smile:",
"smile",
"subspace1",
),
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":fire:",
"fire",
"subspace2",
),
},
req: &types.QueryRegisteredReactionsRequest{},
expLen: 2,
},
{
name: "query registered reactions with a subspace",
storedReactions: []types.RegisteredReaction{
types.NewRegisteredReaction(
"creator",
":smile:",
"smile",
"subspace1",
),
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":fire:",
"fire",
"subspace2",
),
},
req: &types.QueryRegisteredReactionsRequest{Subspace: "subspace1"},
expLen: 1,
},
{
name: "query registered reactions with pagination",
storedReactions: []types.RegisteredReaction{
types.NewRegisteredReaction(
"creator",
":smile:",
"smile",
"subspace1",
),
types.NewRegisteredReaction(
"cosmos1s3nh6tafl4amaxkke9kdejhp09lk93g9ev39r4",
":fire:",
"fire",
"subspace2",
),
},
req: &types.QueryRegisteredReactionsRequest{Pagination: &query.PageRequest{Limit: 1}},
expLen: 1,
},
}

for _, uc := range usecases {
suite.Run(uc.name, func() {
suite.SetupTest()
for _, reaction := range uc.storedReactions {
suite.k.SaveRegisteredReaction(suite.ctx, reaction)
}

res, err := suite.k.RegisteredReactions(sdk.WrapSDKContext(suite.ctx), uc.req)
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(uc.expLen, len(res.RegisteredReactions))
})
}
}
4 changes: 2 additions & 2 deletions x/staging/posts/keeper/keeper_reactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (k Keeper) GetPostReactionsEntries(ctx sdk.Context) []types.PostReactionsEn
// SaveRegisteredReaction allows to register a new reaction for later reference
func (k Keeper) SaveRegisteredReaction(ctx sdk.Context, reaction types.RegisteredReaction) {
store := ctx.KVStore(k.storeKey)
store.Set(types.ReactionsStoreKey(reaction.ShortCode, reaction.Subspace), k.cdc.MustMarshalBinaryBare(&reaction))
store.Set(types.RegisteredReactionsStoreKey(reaction.Subspace, reaction.ShortCode), k.cdc.MustMarshalBinaryBare(&reaction))
}

// GetRegisteredReaction returns the registered reactions which has the given shortcode
Expand All @@ -110,7 +110,7 @@ func (k Keeper) GetRegisteredReaction(
ctx sdk.Context, shortcode string, subspace string,
) (reaction types.RegisteredReaction, exist bool) {
store := ctx.KVStore(k.storeKey)
key := types.ReactionsStoreKey(shortcode, subspace)
key := types.RegisteredReactionsStoreKey(subspace, shortcode)

if !store.Has(key) {
return types.RegisteredReaction{}, false
Expand Down
2 changes: 1 addition & 1 deletion x/staging/posts/simulation/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestDecodeStore(t *testing.T) {
Value: cdc.MustMarshalBinaryBare(&postReactions),
},
{
Key: types.ReactionsStoreKey(registeredReaction.ShortCode, registeredReaction.Subspace),
Key: types.RegisteredReactionsStoreKey(registeredReaction.Subspace, registeredReaction.ShortCode),
Value: cdc.MustMarshalBinaryBare(&registeredReaction),
},
{
Expand Down
11 changes: 8 additions & 3 deletions x/staging/posts/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,14 @@ func PostReactionsStoreKey(id string) []byte {
return append(PostReactionsStorePrefix, []byte(id)...)
}

// ReactionsStoreKey turns the combination of shortCode and subspace to a key used to store a reaction into the reaction's store
func ReactionsStoreKey(shortCode, subspace string) []byte {
return append(ReactionsStorePrefix, []byte(shortCode+subspace)...)
// RegisteredReactionsPrefix returns the prefix used to store all the reactions for the subspace having the given id
func RegisteredReactionsPrefix(subspace string) []byte {
return append(ReactionsStorePrefix, []byte(subspace)...)
}

// RegisteredReactionsStoreKey returns the key used to store the registered reaction having the given short code for the given subspace
func RegisteredReactionsStoreKey(subspace, shortCode string) []byte {
return append(RegisteredReactionsPrefix(subspace), []byte(shortCode)...)
}

// PollAnswersStoreKey turns an id to a key used to store a post's poll answer into the posts store
Expand Down
Loading