github.com/cosmos/cosmos-sdk@v0.50.10/client/utils.go (about) 1 package client 2 3 import ( 4 "encoding/base64" 5 6 rpchttp "github.com/cometbft/cometbft/rpc/client/http" 7 "github.com/spf13/pflag" 8 9 errorsmod "cosmossdk.io/errors" 10 11 "github.com/cosmos/cosmos-sdk/client/flags" 12 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 13 "github.com/cosmos/cosmos-sdk/types/query" 14 ) 15 16 // Paginate returns the correct starting and ending index for a paginated query, 17 // given that client provides a desired page and limit of objects and the handler 18 // provides the total number of objects. The start page is assumed to be 1-indexed. 19 // If the start page is invalid, non-positive values are returned signaling the 20 // request is invalid; it returns non-positive values if limit is non-positive and 21 // defLimit is negative. 22 func Paginate(numObjs, page, limit, defLimit int) (start, end int) { 23 if page <= 0 { 24 // invalid start page 25 return -1, -1 26 } 27 28 // fallback to default limit if supplied limit is invalid 29 if limit <= 0 { 30 if defLimit < 0 { 31 // invalid default limit 32 return -1, -1 33 } 34 limit = defLimit 35 } 36 37 start = (page - 1) * limit 38 end = limit + start 39 40 if end >= numObjs { 41 end = numObjs 42 } 43 44 if start >= numObjs { 45 // page is out of bounds 46 return -1, -1 47 } 48 49 return start, end 50 } 51 52 // ReadPageRequest reads and builds the necessary page request flags for pagination. 53 func ReadPageRequest(flagSet *pflag.FlagSet) (*query.PageRequest, error) { 54 pageKey, _ := flagSet.GetString(flags.FlagPageKey) 55 offset, _ := flagSet.GetUint64(flags.FlagOffset) 56 limit, _ := flagSet.GetUint64(flags.FlagLimit) 57 countTotal, _ := flagSet.GetBool(flags.FlagCountTotal) 58 page, _ := flagSet.GetUint64(flags.FlagPage) 59 reverse, _ := flagSet.GetBool(flags.FlagReverse) 60 61 if page > 1 && offset > 0 { 62 return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "page and offset cannot be used together") 63 } 64 65 if page > 1 { 66 offset = (page - 1) * limit 67 } 68 69 return &query.PageRequest{ 70 Key: []byte(pageKey), 71 Offset: offset, 72 Limit: limit, 73 CountTotal: countTotal, 74 Reverse: reverse, 75 }, nil 76 } 77 78 // NewClientFromNode sets up Client implementation that communicates with a CometBFT node over 79 // JSON RPC and WebSockets 80 func NewClientFromNode(nodeURI string) (*rpchttp.HTTP, error) { 81 return rpchttp.New(nodeURI, "/websocket") 82 } 83 84 // FlagSetWithPageKeyDecoded returns the provided flagSet with the page-key value base64 decoded (if it exists). 85 // This is for when the page-key is provided as a base64 string (e.g. from the CLI). 86 // ReadPageRequest expects it to be the raw bytes. 87 // 88 // Common usage: 89 // fs, err := client.FlagSetWithPageKeyDecoded(cmd.Flags()) 90 // pageReq, err := client.ReadPageRequest(fs) 91 func FlagSetWithPageKeyDecoded(flagSet *pflag.FlagSet) (*pflag.FlagSet, error) { 92 encoded, err := flagSet.GetString(flags.FlagPageKey) 93 if err != nil { 94 return flagSet, err 95 } 96 if len(encoded) > 0 { 97 var raw []byte 98 raw, err = base64.StdEncoding.DecodeString(encoded) 99 if err != nil { 100 return flagSet, err 101 } 102 _ = flagSet.Set(flags.FlagPageKey, string(raw)) 103 } 104 return flagSet, nil 105 } 106 107 // MustFlagSetWithPageKeyDecoded calls FlagSetWithPageKeyDecoded and panics on error. 108 // 109 // Common usage: pageReq, err := client.ReadPageRequest(client.MustFlagSetWithPageKeyDecoded(cmd.Flags())) 110 func MustFlagSetWithPageKeyDecoded(flagSet *pflag.FlagSet) *pflag.FlagSet { 111 rv, err := FlagSetWithPageKeyDecoded(flagSet) 112 if err != nil { 113 panic(err.Error()) 114 } 115 return rv 116 }