-
Notifications
You must be signed in to change notification settings - Fork 31
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
feat: implement pagination for x/wasm query #85
Changes from 3 commits
5eaac52
0421c56
fda259e
1f0c296
87b8e1b
9bf9b68
37abfeb
d270cf6
b3f69cf
d037d18
c35995a
0d36346
365b485
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import ( | |
sdk "github.com/line/lbm-sdk/types" | ||
"github.com/line/lbm-sdk/types/rest" | ||
|
||
"github.com/line/lbm-sdk/x/wasm/client/utils" | ||
"github.com/line/lbm-sdk/x/wasm/internal/keeper" | ||
"github.com/line/lbm-sdk/x/wasm/internal/types" | ||
) | ||
|
@@ -238,7 +239,29 @@ func queryContractHistoryFn(cliCtx context.CLIContext) http.HandlerFunc { | |
} | ||
|
||
route := fmt.Sprintf("custom/%s/%s/%s", types.QuerierRoute, keeper.QueryContractHistory, addr.String()) | ||
res, height, err := cliCtx.Query(route) | ||
pageKey, offset, limit, page, countTotal, err := utils.ParseHTTPArgs(r) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
pageReq, err := utils.NewPageRequest(pageKey, offset, limit, page, countTotal) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
data := &types.QueryContractHistoryRequest{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
Address: addr, | ||
Pagination: pageReq, | ||
} | ||
bs, err := cliCtx.Codec.MarshalJSON(data) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
} | ||
|
||
res, height, err := cliCtx.QueryWithData(route, bs) | ||
if err != nil { | ||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) | ||
return | ||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -3,13 +3,34 @@ package utils | |||||||
import ( | ||||||||
"bytes" | ||||||||
"compress/gzip" | ||||||||
"encoding/binary" | ||||||||
"errors" | ||||||||
"fmt" | ||||||||
"net/http" | ||||||||
"strconv" | ||||||||
|
||||||||
"github.com/spf13/cobra" | ||||||||
"github.com/spf13/pflag" | ||||||||
|
||||||||
sdkerrors "github.com/line/lbm-sdk/types/errors" | ||||||||
"github.com/line/lbm-sdk/types/rest" | ||||||||
"github.com/line/lbm-sdk/x/wasm/internal/types" | ||||||||
) | ||||||||
|
||||||||
var ( | ||||||||
gzipIdent = []byte("\x1F\x8B\x08") | ||||||||
wasmIdent = []byte("\x00\x61\x73\x6D") | ||||||||
) | ||||||||
|
||||||||
// List of CLI flags | ||||||||
const ( | ||||||||
FlagPage = "page" | ||||||||
FlagLimit = "limit" | ||||||||
FlagPageKey = "page-key" | ||||||||
FlagOffset = "offset" | ||||||||
FlagCountTotal = "count-total" | ||||||||
) | ||||||||
|
||||||||
// IsGzip returns checks if the file contents are gzip compressed | ||||||||
func IsGzip(input []byte) bool { | ||||||||
return bytes.Equal(input[:3], gzipIdent) | ||||||||
|
@@ -36,3 +57,117 @@ func GzipIt(input []byte) ([]byte, error) { | |||||||
|
||||||||
return b.Bytes(), nil | ||||||||
} | ||||||||
|
||||||||
// AddPaginationFlagsToCmd adds common pagination flags to cmd | ||||||||
func AddPaginationFlagsToCmd(cmd *cobra.Command, query string) { | ||||||||
cmd.Flags().Uint64(FlagPage, 1, fmt.Sprintf("pagination page of %s to query for. This sets offset to a multiple of limit", query)) | ||||||||
cmd.Flags().String(FlagPageKey, "", fmt.Sprintf("pagination page-key of %s to query for", query)) | ||||||||
cmd.Flags().Uint64(FlagOffset, 0, fmt.Sprintf("pagination offset of %s to query for", query)) | ||||||||
cmd.Flags().Uint64(FlagLimit, 100, fmt.Sprintf("pagination limit of %s to query for", query)) | ||||||||
cmd.Flags().Bool( | ||||||||
FlagCountTotal, false, fmt.Sprintf("count total number of records in %s to query for", query)) | ||||||||
} | ||||||||
|
||||||||
// BigEndianToUint64 returns an uint64 from big endian encoded bytes. If encoding | ||||||||
// is empty, zero is returned. | ||||||||
// This function is included in cosmos-sdk v0.40.0 | ||||||||
// Once cosmos-sdk is updated, use the sdk functions. | ||||||||
func BigEndianToUint64(bz []byte) uint64 { | ||||||||
if len(bz) == 0 { | ||||||||
return 0 | ||||||||
} | ||||||||
|
||||||||
return binary.BigEndian.Uint64(bz) | ||||||||
} | ||||||||
|
||||||||
// ReadPageRequest reads and builds the necessary page request flags for pagination. | ||||||||
func ReadPageRequest(flagSet *pflag.FlagSet) (*types.PageRequest, error) { | ||||||||
pageKey, err := flagSet.GetString(FlagPageKey) | ||||||||
if err != nil { | ||||||||
return nil, err | ||||||||
} | ||||||||
offset, err := flagSet.GetUint64(FlagOffset) | ||||||||
if err != nil { | ||||||||
return nil, err | ||||||||
} | ||||||||
limit, err := flagSet.GetUint64(FlagLimit) | ||||||||
if err != nil { | ||||||||
return nil, err | ||||||||
} | ||||||||
countTotal, err := flagSet.GetBool(FlagCountTotal) | ||||||||
if err != nil { | ||||||||
return nil, err | ||||||||
} | ||||||||
page, err := flagSet.GetUint64(FlagPage) | ||||||||
if err != nil { | ||||||||
return nil, err | ||||||||
} | ||||||||
|
||||||||
return NewPageRequest(pageKey, offset, limit, page, countTotal) | ||||||||
} | ||||||||
|
||||||||
func NewPageRequest(pageKey string, offset, limit, page uint64, countTotal bool) (*types.PageRequest, error) { | ||||||||
if page > 1 && offset > 0 { | ||||||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "page and offset cannot be used together") | ||||||||
} | ||||||||
|
||||||||
if page > 1 { | ||||||||
brew0722 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
offset = (page - 1) * limit | ||||||||
} | ||||||||
|
||||||||
return &types.PageRequest{ | ||||||||
Key: []byte(pageKey), | ||||||||
Offset: offset, | ||||||||
Limit: limit, | ||||||||
CountTotal: countTotal, | ||||||||
}, nil | ||||||||
} | ||||||||
|
||||||||
func ParseHTTPArgs(r *http.Request) (pageKey string, offset, limit, page uint64, countTotal bool, err error) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The pagination utility for HTTP args does already exist. Can we use it for API consistency?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The limit and page could be parseed from the already existing ParseHTTPArgs. |
||||||||
pageKey = r.FormValue("page-key") | ||||||||
|
||||||||
offsetStr := r.FormValue("offset") | ||||||||
if offsetStr != "" { | ||||||||
offset, err = strconv.ParseUint(offsetStr, 10, 64) | ||||||||
if err != nil { | ||||||||
return pageKey, offset, limit, page, countTotal, err | ||||||||
} | ||||||||
if offset <= 0 { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. other than here, used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||
return pageKey, offset, limit, page, countTotal, errors.New("offset must greater than 0") | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
pageStr := r.FormValue("page") | ||||||||
if pageStr == "" { | ||||||||
page = rest.DefaultPage | ||||||||
} else { | ||||||||
page, err = strconv.ParseUint(pageStr, 10, 64) | ||||||||
if err != nil { | ||||||||
return pageKey, offset, limit, page, countTotal, err | ||||||||
} else if page <= 0 { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor comment. As the previous doc says, the following suggestion is better.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: does page index start from 1, not 0? |
||||||||
return pageKey, offset, limit, page, countTotal, errors.New("page must greater than 0") | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
limitStr := r.FormValue("limit") | ||||||||
if limitStr == "" { | ||||||||
limit = rest.DefaultLimit | ||||||||
} else { | ||||||||
limit, err = strconv.ParseUint(limitStr, 10, 64) | ||||||||
if err != nil { | ||||||||
return pageKey, offset, limit, page, countTotal, err | ||||||||
} else if limit <= 0 { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
ditto |
||||||||
return pageKey, offset, limit, page, countTotal, errors.New("limit must greater than 0") | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
countTotalStr := r.FormValue("count-total") | ||||||||
if countTotalStr != "" { | ||||||||
countTotal, err = strconv.ParseBool(countTotalStr) | ||||||||
if err != nil { | ||||||||
return pageKey, offset, limit, page, countTotal, err | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
return pageKey, offset, limit, page, countTotal, nil | ||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think address information is now included in the data field so that we can diet route path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes! it removed.