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  }