Co-authored-by: testinginprod <98415576+testinginprod@users.noreply.github.com> Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
parent
d4284d7f14
commit
d2b61d0bf5
@ -57,6 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
### Bug Fixes
|
||||
|
||||
* (x/bank) [#16841](https://github.com/cosmos/cosmos-sdk/pull/16841) Correctly process legacy `DenomAddressIndex` values.
|
||||
* (types/query) [#16905](https://github.com/cosmos/cosmos-sdk/pull/16905) Collections Pagination now applies proper count when filtering results.
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
|
||||
@ -12,8 +12,8 @@ require (
|
||||
cosmossdk.io/store v1.0.0-alpha.1
|
||||
cosmossdk.io/tools/confix v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/tools/rosetta v0.2.1-0.20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/nft v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/tx v0.9.1
|
||||
|
||||
@ -209,10 +209,10 @@ cosmossdk.io/tools/confix v0.0.0-20230713160716-d4e95eec9f29 h1:uIWFA16Db7llUhWZ
|
||||
cosmossdk.io/tools/confix v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:b/bU9v699JldsEnnsDFGAAem+L1dHA+EWOI4l3Ik1cg=
|
||||
cosmossdk.io/tools/rosetta v0.2.1-0.20230713160716-d4e95eec9f29 h1:7c/8Q6icB72IUkOO47ua2o7/6+GxdmTUmaVbgoP5gOA=
|
||||
cosmossdk.io/tools/rosetta v0.2.1-0.20230713160716-d4e95eec9f29/go.mod h1:jdr/6CIOCmyPd27m3/GyN9I1lDuSmZx+zpsieG3Hdbc=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29 h1:DQqRU/fT8TM8HykDLRCBEsbOgjRe6wPI5SrbWmGvsNE=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:oo7//3TLAxU3sHyCxUeiUmUw0a6VFoXiJs7TR0Te0+4=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29 h1:xzwV67rZifJRCCUSzKlN5s3xPGoj/mlRQW5NLOJ9uCQ=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:SUYYupIrpF2id6W+1VMcDpAfmeglZ3cTIfc0/PLtAHo=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135 h1:Qfywx4oCgJx3TzMiU5MM0R5zQO5dR2m29r6Y3EOAaf0=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135/go.mod h1:jxt8hWrbvtpNAxC1bIh5gojBIqvX2w83wJVquVwsOKM=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135 h1:SWjE56GlSCe5RSMUuC+peWhnkZa4Lbev0fJip3WflbA=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135/go.mod h1:WiGXY9/0GKp0FFKPmNr0OtMxE5MOoRkDeE6HWZE41Pw=
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29 h1:oqmjaQAAYjNo9Sj77IsCuTuuKNN4Q+Py3zwclSDsroU=
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:izdG3ENxO7Z6kSRbZorbRJHarV2efZM63+Xyk27KksU=
|
||||
cosmossdk.io/x/nft v0.0.0-20230713160716-d4e95eec9f29 h1:Orne21OeV4lMN7zdbKQs4/vQAiTpR1IOeX1tFcezXuw=
|
||||
|
||||
@ -12,7 +12,7 @@ require (
|
||||
cosmossdk.io/math v1.0.1
|
||||
cosmossdk.io/simapp v0.0.0-20230620040119-e078f1a49e8b
|
||||
cosmossdk.io/store v1.0.0-alpha.1
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29
|
||||
cosmossdk.io/x/nft v0.0.0-20230713160716-d4e95eec9f29 // indirect
|
||||
cosmossdk.io/x/tx v0.9.1
|
||||
@ -39,7 +39,7 @@ require (
|
||||
cloud.google.com/go/iam v1.1.0 // indirect
|
||||
cloud.google.com/go/storage v1.30.1 // indirect
|
||||
cosmossdk.io/client/v2 v2.0.0-20230713160716-d4e95eec9f29 // indirect
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29 // indirect
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
|
||||
@ -205,10 +205,10 @@ cosmossdk.io/math v1.0.1 h1:Qx3ifyOPaMLNH/89WeZFH268yCvU4xEcnPLu3sJqPPg=
|
||||
cosmossdk.io/math v1.0.1/go.mod h1:Ygz4wBHrgc7g0N+8+MrnTfS9LLn9aaTGa9hKopuym5k=
|
||||
cosmossdk.io/store v1.0.0-alpha.1 h1:/151XxAgm0tiKuYrtJzMG61lf6enpPuP+D/hIN8cRjQ=
|
||||
cosmossdk.io/store v1.0.0-alpha.1/go.mod h1:ejgU9GhRGMNBduVnDwC3RyhOmu4uKlNQlTiJgPmbDkI=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29 h1:DQqRU/fT8TM8HykDLRCBEsbOgjRe6wPI5SrbWmGvsNE=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:oo7//3TLAxU3sHyCxUeiUmUw0a6VFoXiJs7TR0Te0+4=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29 h1:xzwV67rZifJRCCUSzKlN5s3xPGoj/mlRQW5NLOJ9uCQ=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:SUYYupIrpF2id6W+1VMcDpAfmeglZ3cTIfc0/PLtAHo=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135 h1:Qfywx4oCgJx3TzMiU5MM0R5zQO5dR2m29r6Y3EOAaf0=
|
||||
cosmossdk.io/x/circuit v0.0.0-20230713220914-c0369a888135/go.mod h1:jxt8hWrbvtpNAxC1bIh5gojBIqvX2w83wJVquVwsOKM=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135 h1:SWjE56GlSCe5RSMUuC+peWhnkZa4Lbev0fJip3WflbA=
|
||||
cosmossdk.io/x/evidence v0.0.0-20230713220914-c0369a888135/go.mod h1:WiGXY9/0GKp0FFKPmNr0OtMxE5MOoRkDeE6HWZE41Pw=
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29 h1:oqmjaQAAYjNo9Sj77IsCuTuuKNN4Q+Py3zwclSDsroU=
|
||||
cosmossdk.io/x/feegrant v0.0.0-20230713160716-d4e95eec9f29/go.mod h1:izdG3ENxO7Z6kSRbZorbRJHarV2efZM63+Xyk27KksU=
|
||||
cosmossdk.io/x/nft v0.0.0-20230713160716-d4e95eec9f29 h1:Orne21OeV4lMN7zdbKQs4/vQAiTpR1IOeX1tFcezXuw=
|
||||
|
||||
@ -35,24 +35,40 @@ type Collection[K, V any] interface {
|
||||
KeyCodec() collcodec.KeyCodec[K]
|
||||
}
|
||||
|
||||
// CollectionPaginate follows the same behavior as Paginate but works on a Collection.
|
||||
func CollectionPaginate[K, V any, C Collection[K, V]](
|
||||
// CollectionPaginate follows the same logic as Paginate but for collection types.
|
||||
// transformFunc is used to transform the result to a different type.
|
||||
func CollectionPaginate[K, V any, C Collection[K, V], T any](
|
||||
ctx context.Context,
|
||||
coll C,
|
||||
pageReq *PageRequest,
|
||||
) ([]collections.KeyValue[K, V], *PageResponse, error) {
|
||||
return CollectionFilteredPaginate[K, V](ctx, coll, pageReq, nil)
|
||||
transformFunc func(key K, value V) (T, error),
|
||||
opts ...func(opt *CollectionsPaginateOptions[K]),
|
||||
) ([]T, *PageResponse, error) {
|
||||
return CollectionFilteredPaginate(
|
||||
ctx,
|
||||
coll,
|
||||
pageReq,
|
||||
nil,
|
||||
transformFunc,
|
||||
opts...,
|
||||
)
|
||||
}
|
||||
|
||||
// CollectionFilteredPaginate works in the same way as FilteredPaginate but for collection types.
|
||||
// CollectionFilteredPaginate works in the same way as CollectionPaginate but allows to filter
|
||||
// results using a predicateFunc.
|
||||
// A nil predicateFunc means no filtering is applied and results are collected as is.
|
||||
func CollectionFilteredPaginate[K, V any, C Collection[K, V]](
|
||||
// TransformFunc is applied only to results which are in range of the pagination and allow
|
||||
// to convert the result to a different type.
|
||||
// NOTE: do not collect results using the values/keys passed to predicateFunc as they are not
|
||||
// guaranteed to be in the pagination range requested.
|
||||
func CollectionFilteredPaginate[K, V any, C Collection[K, V], T any](
|
||||
ctx context.Context,
|
||||
coll C,
|
||||
pageReq *PageRequest,
|
||||
predicateFunc func(key K, value V) (include bool, err error),
|
||||
transformFunc func(key K, value V) (T, error),
|
||||
opts ...func(opt *CollectionsPaginateOptions[K]),
|
||||
) ([]collections.KeyValue[K, V], *PageResponse, error) {
|
||||
) (results []T, pageRes *PageResponse, err error) {
|
||||
pageReq = initPageRequestDefaults(pageReq)
|
||||
|
||||
offset := pageReq.Offset
|
||||
@ -65,12 +81,6 @@ func CollectionFilteredPaginate[K, V any, C Collection[K, V]](
|
||||
return nil, nil, fmt.Errorf("invalid request, either offset or key is expected, got both")
|
||||
}
|
||||
|
||||
var (
|
||||
results []collections.KeyValue[K, V]
|
||||
pageRes *PageResponse
|
||||
err error
|
||||
)
|
||||
|
||||
opt := new(CollectionsPaginateOptions[K])
|
||||
for _, o := range opts {
|
||||
o(opt)
|
||||
@ -85,9 +95,9 @@ func CollectionFilteredPaginate[K, V any, C Collection[K, V]](
|
||||
}
|
||||
|
||||
if len(key) != 0 {
|
||||
results, pageRes, err = collFilteredPaginateByKey(ctx, coll, prefix, key, reverse, limit, predicateFunc)
|
||||
results, pageRes, err = collFilteredPaginateByKey(ctx, coll, prefix, key, reverse, limit, predicateFunc, transformFunc)
|
||||
} else {
|
||||
results, pageRes, err = collFilteredPaginateNoKey(ctx, coll, prefix, reverse, offset, limit, countTotal, predicateFunc)
|
||||
results, pageRes, err = collFilteredPaginateNoKey(ctx, coll, prefix, reverse, offset, limit, countTotal, predicateFunc, transformFunc)
|
||||
}
|
||||
// invalid iter error is ignored to retain Paginate behavior
|
||||
if errors.Is(err, collections.ErrInvalidIterator) {
|
||||
@ -102,7 +112,7 @@ func CollectionFilteredPaginate[K, V any, C Collection[K, V]](
|
||||
|
||||
// collFilteredPaginateNoKey applies the provided pagination on the collection when the starting key is not set.
|
||||
// If predicateFunc is nil no filtering is applied.
|
||||
func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
func collFilteredPaginateNoKey[K, V any, C Collection[K, V], T any](
|
||||
ctx context.Context,
|
||||
coll C,
|
||||
prefix []byte,
|
||||
@ -111,7 +121,8 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
limit uint64,
|
||||
countTotal bool,
|
||||
predicateFunc func(K, V) (bool, error),
|
||||
) ([]collections.KeyValue[K, V], *PageResponse, error) {
|
||||
transformFunc func(K, V) (T, error),
|
||||
) ([]T, *PageResponse, error) {
|
||||
iterator, err := getCollIter[K, V](ctx, coll, prefix, nil, reverse)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -125,7 +136,7 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
var (
|
||||
count uint64
|
||||
nextKey []byte
|
||||
results []collections.KeyValue[K, V]
|
||||
results []T
|
||||
)
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
@ -138,7 +149,13 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
}
|
||||
// if no predicate function is specified then we just include the result
|
||||
if predicateFunc == nil {
|
||||
results = append(results, kv)
|
||||
transformed, err := transformFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
results = append(results, transformed)
|
||||
count++
|
||||
|
||||
// if predicate function is defined we check if the result matches the filtering criteria
|
||||
} else {
|
||||
include, err := predicateFunc(kv.Key, kv.Value)
|
||||
@ -146,10 +163,14 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
return nil, nil, err
|
||||
}
|
||||
if include {
|
||||
results = append(results, kv)
|
||||
transformed, err := transformFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
results = append(results, transformed)
|
||||
count++
|
||||
}
|
||||
}
|
||||
count++
|
||||
// second case, we found all the objects specified within the limit
|
||||
case count == limit:
|
||||
key, err := iterator.Key()
|
||||
@ -172,12 +193,31 @@ func collFilteredPaginateNoKey[K, V any, C Collection[K, V]](
|
||||
// but we need to count how many possible results exist in total.
|
||||
// so we keep increasing the count until the iterator is fully consumed.
|
||||
case count > limit:
|
||||
count++
|
||||
if predicateFunc == nil {
|
||||
count++
|
||||
|
||||
// if predicate function is defined we check if the result matches the filtering criteria
|
||||
} else {
|
||||
kv, err := iterator.KeyValue()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
include, err := predicateFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if include {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resp := &PageResponse{
|
||||
NextKey: nextKey,
|
||||
}
|
||||
|
||||
if countTotal {
|
||||
resp.Total = count + offset
|
||||
}
|
||||
@ -200,15 +240,16 @@ func advanceIter[I interface {
|
||||
|
||||
// collFilteredPaginateByKey paginates a collection when a starting key
|
||||
// is provided in the PageRequest. Predicate is applied only if not nil.
|
||||
func collFilteredPaginateByKey[K, V any, C Collection[K, V]](
|
||||
func collFilteredPaginateByKey[K, V any, C Collection[K, V], T any](
|
||||
ctx context.Context,
|
||||
coll C,
|
||||
prefix []byte,
|
||||
key []byte,
|
||||
reverse bool,
|
||||
limit uint64,
|
||||
predicateFunc func(K, V) (bool, error),
|
||||
) ([]collections.KeyValue[K, V], *PageResponse, error) {
|
||||
predicateFunc func(key K, value V) (bool, error),
|
||||
transformFunc func(key K, value V) (transformed T, err error),
|
||||
) (results []T, pageRes *PageResponse, err error) {
|
||||
iterator, err := getCollIter[K, V](ctx, coll, prefix, key, reverse)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -218,7 +259,6 @@ func collFilteredPaginateByKey[K, V any, C Collection[K, V]](
|
||||
var (
|
||||
count uint64
|
||||
nextKey []byte
|
||||
results []collections.KeyValue[K, V]
|
||||
)
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
@ -243,7 +283,11 @@ func collFilteredPaginateByKey[K, V any, C Collection[K, V]](
|
||||
}
|
||||
// if no predicate is specified then we just append the result
|
||||
if predicateFunc == nil {
|
||||
results = append(results, kv)
|
||||
transformed, err := transformFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
results = append(results, transformed)
|
||||
// if predicate is applied we execute the predicate function
|
||||
// and append only if predicateFunc yields true.
|
||||
} else {
|
||||
@ -252,7 +296,11 @@ func collFilteredPaginateByKey[K, V any, C Collection[K, V]](
|
||||
return nil, nil, err
|
||||
}
|
||||
if include {
|
||||
results = append(results, kv)
|
||||
transformed, err := transformFunc(kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
results = append(results, transformed)
|
||||
}
|
||||
}
|
||||
count++
|
||||
|
||||
@ -100,7 +100,7 @@ func TestCollectionPagination(t *testing.T) {
|
||||
Limit: 3,
|
||||
},
|
||||
expResp: &PageResponse{
|
||||
NextKey: encodeKey(3),
|
||||
NextKey: encodeKey(5),
|
||||
},
|
||||
filter: func(key, value uint64) (bool, error) {
|
||||
return key%2 == 0, nil
|
||||
@ -108,6 +108,7 @@ func TestCollectionPagination(t *testing.T) {
|
||||
expResults: []collections.KeyValue[uint64, uint64]{
|
||||
{Key: 0, Value: 0},
|
||||
{Key: 2, Value: 2},
|
||||
{Key: 4, Value: 4},
|
||||
},
|
||||
},
|
||||
"filtered with key": {
|
||||
@ -131,7 +132,15 @@ func TestCollectionPagination(t *testing.T) {
|
||||
for name, tc := range tcs {
|
||||
tc := tc
|
||||
t.Run(name, func(t *testing.T) {
|
||||
gotResults, gotResponse, err := CollectionFilteredPaginate(ctx, m, tc.req, tc.filter)
|
||||
gotResults, gotResponse, err := CollectionFilteredPaginate(
|
||||
ctx,
|
||||
m,
|
||||
tc.req,
|
||||
tc.filter,
|
||||
func(key, value uint64) (collections.KeyValue[uint64, uint64], error) {
|
||||
return collections.KeyValue[uint64, uint64]{Key: key, Value: value}, nil
|
||||
},
|
||||
)
|
||||
if tc.wantErr != nil {
|
||||
require.ErrorIs(t, err, tc.wantErr)
|
||||
return
|
||||
|
||||
@ -47,15 +47,14 @@ func (s queryServer) Accounts(ctx context.Context, req *types.QueryAccountsReque
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
var accounts []*codectypes.Any
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, s.k.Accounts, req.Pagination, func(_ sdk.AccAddress, value sdk.AccountI) (include bool, err error) {
|
||||
accountAny, err := codectypes.NewAnyWithValue(value)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
accounts = append(accounts, accountAny)
|
||||
return false, nil // we don't include it since we're already appending the account
|
||||
})
|
||||
accounts, pageRes, err := query.CollectionPaginate(
|
||||
ctx,
|
||||
s.k.Accounts,
|
||||
req.Pagination,
|
||||
func(_ sdk.AccAddress, value sdk.AccountI) (*codectypes.Any, error) {
|
||||
return codectypes.NewAnyWithValue(value)
|
||||
},
|
||||
)
|
||||
|
||||
return &types.QueryAccountsResponse{Accounts: accounts, Pagination: pageRes}, err
|
||||
}
|
||||
|
||||
@ -59,19 +59,20 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances
|
||||
}
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
||||
|
||||
balances := sdk.NewCoins()
|
||||
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, k.Balances, req.Pagination, func(key collections.Pair[sdk.AccAddress, string], value math.Int) (include bool, err error) {
|
||||
denom := key.K2()
|
||||
if req.ResolveDenom {
|
||||
if metadata, ok := k.GetDenomMetaData(sdkCtx, denom); ok {
|
||||
denom = metadata.Display
|
||||
balances, pageRes, err := query.CollectionPaginate(
|
||||
ctx,
|
||||
k.Balances,
|
||||
req.Pagination,
|
||||
func(key collections.Pair[sdk.AccAddress, string], value math.Int) (sdk.Coin, error) {
|
||||
if req.ResolveDenom {
|
||||
if metadata, ok := k.GetDenomMetaData(sdkCtx, key.K2()); ok {
|
||||
return sdk.NewCoin(metadata.Display, value), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
balances = append(balances, sdk.NewCoin(denom, value))
|
||||
return false, nil // we don't include results because we're appending them here.
|
||||
}, query.WithCollectionPaginationPairPrefix[sdk.AccAddress, string](addr))
|
||||
return sdk.NewCoin(key.K2(), value), nil
|
||||
},
|
||||
query.WithCollectionPaginationPairPrefix[sdk.AccAddress, string](addr),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "paginate: %v", err)
|
||||
}
|
||||
@ -93,12 +94,10 @@ func (k BaseKeeper) SpendableBalances(ctx context.Context, req *types.QuerySpend
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
||||
|
||||
balances := sdk.NewCoins()
|
||||
zeroAmt := math.ZeroInt()
|
||||
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, k.Balances, req.Pagination, func(key collections.Pair[sdk.AccAddress, string], _ math.Int) (include bool, err error) {
|
||||
balances = append(balances, sdk.NewCoin(key.K2(), zeroAmt))
|
||||
return false, nil // not including results as they're appended here
|
||||
balances, pageRes, err := query.CollectionPaginate(ctx, k.Balances, req.Pagination, func(key collections.Pair[sdk.AccAddress, string], _ math.Int) (coin sdk.Coin, err error) {
|
||||
return sdk.NewCoin(key.K2(), zeroAmt), nil
|
||||
}, query.WithCollectionPaginationPairPrefix[sdk.AccAddress, string](addr))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "paginate: %v", err)
|
||||
@ -236,19 +235,16 @@ func (k BaseKeeper) DenomOwners(
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
var denomOwners []*types.DenomOwner
|
||||
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(goCtx, k.Balances.Indexes.Denom, req.Pagination,
|
||||
func(key collections.Pair[string, sdk.AccAddress], value collections.NoValue) (include bool, err error) {
|
||||
denomOwners, pageRes, err := query.CollectionPaginate(
|
||||
goCtx,
|
||||
k.Balances.Indexes.Denom,
|
||||
req.Pagination,
|
||||
func(key collections.Pair[string, sdk.AccAddress], value collections.NoValue) (*types.DenomOwner, error) {
|
||||
amt, err := k.Balances.Get(goCtx, collections.Join(key.K2(), req.Denom))
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
denomOwners = append(denomOwners, &types.DenomOwner{
|
||||
Address: key.K2().String(),
|
||||
Balance: sdk.NewCoin(req.Denom, amt),
|
||||
})
|
||||
return false, nil
|
||||
return &types.DenomOwner{Address: key.K2().String(), Balance: sdk.NewCoin(req.Denom, amt)}, nil
|
||||
},
|
||||
query.WithCollectionPaginationPairPrefix[string, sdk.AccAddress](req.Denom),
|
||||
)
|
||||
@ -272,16 +268,17 @@ func (k BaseKeeper) SendEnabled(goCtx context.Context, req *types.QuerySendEnabl
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results, pageResp, err := query.CollectionPaginate[string, bool](ctx, k.BaseViewKeeper.SendEnabled, req.Pagination)
|
||||
results, pageResp, err := query.CollectionPaginate(
|
||||
ctx,
|
||||
k.BaseViewKeeper.SendEnabled,
|
||||
req.Pagination, func(key string, value bool) (*types.SendEnabled, error) {
|
||||
return types.NewSendEnabled(key, value), nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
for _, r := range results {
|
||||
resp.SendEnabled = append(resp.SendEnabled, &types.SendEnabled{
|
||||
Denom: r.Key,
|
||||
Enabled: r.Value,
|
||||
})
|
||||
}
|
||||
resp.SendEnabled = results
|
||||
resp.Pagination = pageResp
|
||||
}
|
||||
|
||||
|
||||
@ -69,14 +69,12 @@ type MintingRestrictionFn func(ctx context.Context, coins sdk.Coins) error
|
||||
|
||||
// GetPaginatedTotalSupply queries for the supply, ignoring 0 coins, with a given pagination
|
||||
func (k BaseKeeper) GetPaginatedTotalSupply(ctx context.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error) {
|
||||
results, pageResp, err := query.CollectionPaginate[string, math.Int](ctx, k.Supply, pagination)
|
||||
coins, pageResp, err := query.CollectionPaginate(ctx, k.Supply, pagination, func(key string, value math.Int) (sdk.Coin, error) {
|
||||
return sdk.NewCoin(key, value), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
coins := sdk.NewCoins()
|
||||
for _, res := range results {
|
||||
coins = coins.Add(sdk.NewCoin(res.Key, res.Value))
|
||||
}
|
||||
|
||||
return coins, pageResp, nil
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ require (
|
||||
cosmossdk.io/store v1.0.0-alpha.1
|
||||
github.com/cockroachdb/errors v1.10.0
|
||||
github.com/cometbft/cometbft v0.38.0-rc2
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22
|
||||
github.com/cosmos/gogoproto v1.4.10
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
|
||||
@ -168,8 +168,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0
|
||||
github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4 h1:7W1dwR+b81odxtPX3LrRHjsBun+9EbMzrSi7rFeEdNY=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4/go.mod h1:6RlLvQl5prjf/lX8lugfXT/YYSQS8fB5Xj/5mdKjCYA=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22 h1:rV/Ch6sUsdw+goeBtVmorls4GPm52oyZgvxUELXjRQ8=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22/go.mod h1:dZ6guNQwL28MFTnKS8sCLM04cHDQ3iivrGRRtKj0Q2c=
|
||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||
github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=
|
||||
|
||||
@ -42,26 +42,26 @@ func (qs QueryServer) Account(c context.Context, req *types.QueryAccountRequest)
|
||||
|
||||
// Account returns account permissions.
|
||||
func (qs QueryServer) Accounts(ctx context.Context, req *types.QueryAccountsRequest) (*types.AccountsResponse, error) {
|
||||
var accounts []*types.GenesisAccountPermissions
|
||||
results, pageRes, err := query.CollectionPaginate[[]byte, types.Permissions](ctx, qs.keeper.Permissions, req.Pagination)
|
||||
results, pageRes, err := query.CollectionPaginate(
|
||||
ctx,
|
||||
qs.keeper.Permissions,
|
||||
req.Pagination,
|
||||
func(key []byte, value types.Permissions) (*types.GenesisAccountPermissions, error) {
|
||||
addrStr, err := qs.keeper.addressCodec.BytesToString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.GenesisAccountPermissions{
|
||||
Address: addrStr,
|
||||
Permissions: &value,
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, result := range results {
|
||||
result := result
|
||||
address, err := qs.keeper.addressCodec.BytesToString(result.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accounts = append(accounts, &types.GenesisAccountPermissions{
|
||||
Address: address,
|
||||
Permissions: &result.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return &types.AccountsResponse{Accounts: accounts, Pagination: pageRes}, nil
|
||||
return &types.AccountsResponse{Accounts: results, Pagination: pageRes}, nil
|
||||
}
|
||||
|
||||
// DisabledList returns a list of disabled message urls
|
||||
|
||||
@ -13,7 +13,7 @@ require (
|
||||
cosmossdk.io/store v1.0.0-alpha.1
|
||||
github.com/cometbft/cometbft v0.38.0-rc2
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22
|
||||
github.com/cosmos/gogoproto v1.4.10
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
|
||||
@ -175,8 +175,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0
|
||||
github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4 h1:7W1dwR+b81odxtPX3LrRHjsBun+9EbMzrSi7rFeEdNY=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713153355-bc7221f5c5f4/go.mod h1:6RlLvQl5prjf/lX8lugfXT/YYSQS8fB5Xj/5mdKjCYA=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22 h1:rV/Ch6sUsdw+goeBtVmorls4GPm52oyZgvxUELXjRQ8=
|
||||
github.com/cosmos/cosmos-sdk v0.50.0-alpha.1.0.20230713220735-0886e25cbe22/go.mod h1:dZ6guNQwL28MFTnKS8sCLM04cHDQ3iivrGRRtKj0Q2c=
|
||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||
github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=
|
||||
|
||||
@ -68,18 +68,12 @@ func (k Querier) AllEvidence(ctx context.Context, req *types.QueryAllEvidenceReq
|
||||
return nil, status.Errorf(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
var evidence []*codectypes.Any
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, k.k.Evidences, req.Pagination, func(_ []byte, value exported.Evidence) (include bool, err error) {
|
||||
evidenceAny, err := codectypes.NewAnyWithValue(value)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
evidence = append(evidence, evidenceAny)
|
||||
return false, nil // we don't include results because we're appending them
|
||||
evidences, pageRes, err := query.CollectionPaginate(ctx, k.k.Evidences, req.Pagination, func(_ []byte, value exported.Evidence) (*codectypes.Any, error) {
|
||||
return codectypes.NewAnyWithValue(value)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.QueryAllEvidenceResponse{Evidence: evidence, Pagination: pageRes}, nil
|
||||
return &types.QueryAllEvidenceResponse{Evidence: evidences, Pagination: pageRes}, nil
|
||||
}
|
||||
|
||||
@ -56,8 +56,7 @@ func (q queryServer) Proposal(ctx context.Context, req *v1.QueryProposalRequest)
|
||||
|
||||
// Proposals implements the Query/Proposals gRPC method
|
||||
func (q queryServer) Proposals(ctx context.Context, req *v1.QueryProposalsRequest) (*v1.QueryProposalsResponse, error) {
|
||||
var filteredProposals []*v1.Proposal
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, q.k.Proposals, req.Pagination, func(key uint64, p v1.Proposal) (bool, error) {
|
||||
filteredProposals, pageRes, err := query.CollectionFilteredPaginate(ctx, q.k.Proposals, req.Pagination, func(key uint64, p v1.Proposal) (include bool, err error) {
|
||||
matchVoter, matchDepositor, matchStatus := true, true, true
|
||||
|
||||
// match status (if supplied/valid)
|
||||
@ -90,11 +89,14 @@ func (q queryServer) Proposals(ctx context.Context, req *v1.QueryProposalsReques
|
||||
|
||||
// if all match, append to results
|
||||
if matchVoter && matchDepositor && matchStatus {
|
||||
filteredProposals = append(filteredProposals, &p)
|
||||
return true, nil
|
||||
}
|
||||
// continue to next item, do not include because we're appending results above.
|
||||
return false, nil
|
||||
}, func(_ uint64, value v1.Proposal) (*v1.Proposal, error) {
|
||||
return &value, nil
|
||||
})
|
||||
|
||||
if err != nil && !errors.IsOf(err, collections.ErrInvalidIterator) {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
@ -142,10 +144,8 @@ func (q queryServer) Votes(ctx context.Context, req *v1.QueryVotesRequest) (*v1.
|
||||
return nil, status.Error(codes.InvalidArgument, "proposal id can not be 0")
|
||||
}
|
||||
|
||||
var votes v1.Votes
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, q.k.Votes, req.Pagination, func(_ collections.Pair[uint64, sdk.AccAddress], value v1.Vote) (include bool, err error) {
|
||||
votes = append(votes, &value)
|
||||
return false, nil // not including results because they're being appended.
|
||||
votes, pageRes, err := query.CollectionPaginate(ctx, q.k.Votes, req.Pagination, func(_ collections.Pair[uint64, sdk.AccAddress], value v1.Vote) (vote *v1.Vote, err error) {
|
||||
return &value, nil
|
||||
}, query.WithCollectionPaginationPairPrefix[uint64, sdk.AccAddress](req.ProposalId))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
@ -227,9 +227,8 @@ func (q queryServer) Deposits(ctx context.Context, req *v1.QueryDepositsRequest)
|
||||
}
|
||||
|
||||
var deposits []*v1.Deposit
|
||||
_, pageRes, err := query.CollectionFilteredPaginate(ctx, q.k.Deposits, req.Pagination, func(_ collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (bool, error) {
|
||||
deposits = append(deposits, &deposit)
|
||||
return false, nil // we don't include results as they're being appended to the slice above.
|
||||
deposits, pageRes, err := query.CollectionPaginate(ctx, q.k.Deposits, req.Pagination, func(_ collections.Pair[uint64, sdk.AccAddress], deposit v1.Deposit) (*v1.Deposit, error) {
|
||||
return &deposit, nil
|
||||
}, query.WithCollectionPaginationPairPrefix[uint64, sdk.AccAddress](req.ProposalId))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
|
||||
@ -233,7 +233,7 @@ func (suite *KeeperTestSuite) TestGRPCQueryProposals() {
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request 2nd page with limit 4",
|
||||
"request 2nd page with limit 3",
|
||||
func() {
|
||||
req = &v1.QueryProposalsRequest{
|
||||
Pagination: &query.PageRequest{Offset: 3, Limit: 3},
|
||||
@ -305,6 +305,70 @@ func (suite *KeeperTestSuite) TestGRPCQueryProposals() {
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request with filter of status voting period",
|
||||
func() {
|
||||
req = &v1.QueryProposalsRequest{
|
||||
ProposalStatus: v1.StatusVotingPeriod,
|
||||
}
|
||||
|
||||
var proposals []*v1.Proposal
|
||||
for i := 0; i < len(testProposals); i++ {
|
||||
if testProposals[i].GetStatus() == v1.StatusVotingPeriod {
|
||||
proposals = append(proposals, testProposals[i])
|
||||
}
|
||||
}
|
||||
|
||||
expRes = &v1.QueryProposalsResponse{
|
||||
Proposals: proposals,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request with filter of status deposit period",
|
||||
func() {
|
||||
req = &v1.QueryProposalsRequest{
|
||||
ProposalStatus: v1.StatusDepositPeriod,
|
||||
}
|
||||
|
||||
var proposals []*v1.Proposal
|
||||
for i := 0; i < len(testProposals); i++ {
|
||||
if testProposals[i].GetStatus() == v1.StatusDepositPeriod {
|
||||
proposals = append(proposals, testProposals[i])
|
||||
}
|
||||
}
|
||||
|
||||
expRes = &v1.QueryProposalsResponse{
|
||||
Proposals: proposals,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"request with filter of status deposit period with limit 2",
|
||||
func() {
|
||||
req = &v1.QueryProposalsRequest{
|
||||
ProposalStatus: v1.StatusDepositPeriod,
|
||||
Pagination: &query.PageRequest{
|
||||
Limit: 2,
|
||||
CountTotal: true,
|
||||
},
|
||||
}
|
||||
|
||||
var proposals []*v1.Proposal
|
||||
for i := 0; i < len(testProposals) && len(proposals) < 2; i++ {
|
||||
if testProposals[i].GetStatus() == v1.StatusDepositPeriod {
|
||||
proposals = append(proposals, testProposals[i])
|
||||
}
|
||||
}
|
||||
|
||||
expRes = &v1.QueryProposalsResponse{
|
||||
Proposals: proposals,
|
||||
}
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user