Add AllDenomMetadata BankQuery (#1426)
* x/wasm: add AllDenomMetadata BankQuery * x/wasm: fix AllDenomMetadata BankQuery to have pagination and add DenomMetadata BankQuery * Use simplified pagination * Fix request conversion * Add unknown denom test cases * Add test for pagination conversion * Fix nits * Use wasmvm 1.3.0-rc.0 * Fix test --------- Co-authored-by: Nikhil Suri <nikhilsuri@comcast.net>
This commit is contained in:
@@ -10,5 +10,6 @@ func AllCapabilities() []string {
|
|||||||
"stargate",
|
"stargate",
|
||||||
"cosmwasm_1_1",
|
"cosmwasm_1_1",
|
||||||
"cosmwasm_1_2",
|
"cosmwasm_1_2",
|
||||||
|
"cosmwasm_1_3",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,18 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
errorsmod "cosmossdk.io/errors"
|
errorsmod "cosmossdk.io/errors"
|
||||||
|
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||||
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
|
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
|
||||||
abci "github.com/cometbft/cometbft/abci/types"
|
abci "github.com/cometbft/cometbft/abci/types"
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/query"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
|
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
|
||||||
|
|
||||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type QueryHandler struct {
|
type QueryHandler struct {
|
||||||
@@ -201,6 +202,27 @@ func BankQuerier(bankKeeper types.BankViewKeeper) func(ctx sdk.Context, request
|
|||||||
}
|
}
|
||||||
return json.Marshal(res)
|
return json.Marshal(res)
|
||||||
}
|
}
|
||||||
|
if request.DenomMetadata != nil {
|
||||||
|
denomMetadata, ok := bankKeeper.GetDenomMetaData(ctx, request.DenomMetadata.Denom)
|
||||||
|
if !ok {
|
||||||
|
return nil, errorsmod.Wrap(sdkerrors.ErrNotFound, request.DenomMetadata.Denom)
|
||||||
|
}
|
||||||
|
res := wasmvmtypes.DenomMetadataResponse{
|
||||||
|
Metadata: ConvertSdkDenomMetadataToWasmDenomMetadata(denomMetadata),
|
||||||
|
}
|
||||||
|
return json.Marshal(res)
|
||||||
|
}
|
||||||
|
if request.AllDenomMetadata != nil {
|
||||||
|
bankQueryRes, err := bankKeeper.DenomsMetadata(ctx, ConvertToDenomsMetadataRequest(request.AllDenomMetadata))
|
||||||
|
if err != nil {
|
||||||
|
return nil, sdkerrors.ErrInvalidRequest
|
||||||
|
}
|
||||||
|
res := wasmvmtypes.AllDenomMetadataResponse{
|
||||||
|
Metadata: ConvertSdkDenomMetadatasToWasmDenomMetadatas(bankQueryRes.Metadatas),
|
||||||
|
NextKey: bankQueryRes.Pagination.NextKey,
|
||||||
|
}
|
||||||
|
return json.Marshal(res)
|
||||||
|
}
|
||||||
return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown BankQuery variant"}
|
return nil, wasmvmtypes.UnsupportedRequest{Kind: "unknown BankQuery variant"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -584,6 +606,51 @@ func ConvertSdkCoinToWasmCoin(coin sdk.Coin) wasmvmtypes.Coin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConvertToDenomsMetadataRequest(wasmRequest *wasmvmtypes.AllDenomMetadataQuery) *banktypes.QueryDenomsMetadataRequest {
|
||||||
|
ret := &banktypes.QueryDenomsMetadataRequest{}
|
||||||
|
if wasmRequest.Pagination != nil {
|
||||||
|
ret.Pagination = &query.PageRequest{
|
||||||
|
Key: wasmRequest.Pagination.Key,
|
||||||
|
Limit: uint64(wasmRequest.Pagination.Limit),
|
||||||
|
Reverse: wasmRequest.Pagination.Reverse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertSdkDenomMetadatasToWasmDenomMetadatas(metadata []banktypes.Metadata) []wasmvmtypes.DenomMetadata {
|
||||||
|
converted := make([]wasmvmtypes.DenomMetadata, len(metadata))
|
||||||
|
for i, m := range metadata {
|
||||||
|
converted[i] = ConvertSdkDenomMetadataToWasmDenomMetadata(m)
|
||||||
|
}
|
||||||
|
return converted
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertSdkDenomMetadataToWasmDenomMetadata(metadata banktypes.Metadata) wasmvmtypes.DenomMetadata {
|
||||||
|
return wasmvmtypes.DenomMetadata{
|
||||||
|
Description: metadata.Description,
|
||||||
|
DenomUnits: ConvertSdkDenomUnitsToWasmDenomUnits(metadata.DenomUnits),
|
||||||
|
Base: metadata.Base,
|
||||||
|
Display: metadata.Display,
|
||||||
|
Name: metadata.Name,
|
||||||
|
Symbol: metadata.Symbol,
|
||||||
|
URI: metadata.URI,
|
||||||
|
URIHash: metadata.URIHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvertSdkDenomUnitsToWasmDenomUnits(denomUnits []*banktypes.DenomUnit) []wasmvmtypes.DenomUnit {
|
||||||
|
converted := make([]wasmvmtypes.DenomUnit, len(denomUnits))
|
||||||
|
for i, u := range denomUnits {
|
||||||
|
converted[i] = wasmvmtypes.DenomUnit{
|
||||||
|
Denom: u.Denom,
|
||||||
|
Exponent: u.Exponent,
|
||||||
|
Aliases: u.Aliases,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return converted
|
||||||
|
}
|
||||||
|
|
||||||
// ConvertProtoToJSONMarshal unmarshals the given bytes into a proto message and then marshals it to json.
|
// ConvertProtoToJSONMarshal unmarshals the given bytes into a proto message and then marshals it to json.
|
||||||
// This is done so that clients calling stargate queries do not need to define their own proto unmarshalers,
|
// This is done so that clients calling stargate queries do not need to define their own proto unmarshalers,
|
||||||
// being able to use response directly by json marshalling, which is supported in cosmwasm.
|
// being able to use response directly by json marshalling, which is supported in cosmwasm.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package keeper_test
|
package keeper_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -356,6 +357,133 @@ func TestBankQuerierBalance(t *testing.T) {
|
|||||||
assert.Equal(t, exp, got)
|
assert.Equal(t, exp, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBankQuerierMetadata(t *testing.T) {
|
||||||
|
metadata := banktypes.Metadata{
|
||||||
|
Name: "Test Token",
|
||||||
|
Base: "utest",
|
||||||
|
DenomUnits: []*banktypes.DenomUnit{
|
||||||
|
{
|
||||||
|
Denom: "utest",
|
||||||
|
Exponent: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mock := bankKeeperMock{GetDenomMetadataFn: func(ctx sdk.Context, denom string) (banktypes.Metadata, bool) {
|
||||||
|
if denom == "utest" {
|
||||||
|
return metadata, true
|
||||||
|
} else {
|
||||||
|
return banktypes.Metadata{}, false
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
ctx := sdk.Context{}
|
||||||
|
q := keeper.BankQuerier(mock)
|
||||||
|
gotBz, gotErr := q(ctx, &wasmvmtypes.BankQuery{
|
||||||
|
DenomMetadata: &wasmvmtypes.DenomMetadataQuery{
|
||||||
|
Denom: "utest",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, gotErr)
|
||||||
|
var got wasmvmtypes.DenomMetadataResponse
|
||||||
|
require.NoError(t, json.Unmarshal(gotBz, &got))
|
||||||
|
exp := wasmvmtypes.DenomMetadata{
|
||||||
|
Name: "Test Token",
|
||||||
|
Base: "utest",
|
||||||
|
DenomUnits: []wasmvmtypes.DenomUnit{
|
||||||
|
{
|
||||||
|
Denom: "utest",
|
||||||
|
Exponent: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, exp, got.Metadata)
|
||||||
|
|
||||||
|
_, gotErr2 := q(ctx, &wasmvmtypes.BankQuery{
|
||||||
|
DenomMetadata: &wasmvmtypes.DenomMetadataQuery{
|
||||||
|
Denom: "uatom",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.Error(t, gotErr2)
|
||||||
|
assert.Contains(t, gotErr2.Error(), "uatom: not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBankQuerierAllMetadata(t *testing.T) {
|
||||||
|
metadata := []banktypes.Metadata{
|
||||||
|
{
|
||||||
|
Name: "Test Token",
|
||||||
|
Base: "utest",
|
||||||
|
DenomUnits: []*banktypes.DenomUnit{
|
||||||
|
{
|
||||||
|
Denom: "utest",
|
||||||
|
Exponent: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
mock := bankKeeperMock{GetDenomsMetadataFn: func(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) {
|
||||||
|
return &banktypes.QueryDenomsMetadataResponse{
|
||||||
|
Metadatas: metadata,
|
||||||
|
Pagination: &query.PageResponse{},
|
||||||
|
}, nil
|
||||||
|
}}
|
||||||
|
|
||||||
|
ctx := sdk.Context{}
|
||||||
|
q := keeper.BankQuerier(mock)
|
||||||
|
gotBz, gotErr := q(ctx, &wasmvmtypes.BankQuery{
|
||||||
|
AllDenomMetadata: &wasmvmtypes.AllDenomMetadataQuery{},
|
||||||
|
})
|
||||||
|
require.NoError(t, gotErr)
|
||||||
|
var got wasmvmtypes.AllDenomMetadataResponse
|
||||||
|
require.NoError(t, json.Unmarshal(gotBz, &got))
|
||||||
|
exp := wasmvmtypes.AllDenomMetadataResponse{
|
||||||
|
Metadata: []wasmvmtypes.DenomMetadata{
|
||||||
|
{
|
||||||
|
Name: "Test Token",
|
||||||
|
Base: "utest",
|
||||||
|
DenomUnits: []wasmvmtypes.DenomUnit{
|
||||||
|
{
|
||||||
|
Denom: "utest",
|
||||||
|
Exponent: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, exp, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBankQuerierAllMetadataPagination(t *testing.T) {
|
||||||
|
var capturedPagination *query.PageRequest
|
||||||
|
mock := bankKeeperMock{GetDenomsMetadataFn: func(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) {
|
||||||
|
capturedPagination = req.Pagination
|
||||||
|
return &banktypes.QueryDenomsMetadataResponse{
|
||||||
|
Metadatas: []banktypes.Metadata{},
|
||||||
|
Pagination: &query.PageResponse{
|
||||||
|
NextKey: nil,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}}
|
||||||
|
|
||||||
|
ctx := sdk.Context{}
|
||||||
|
q := keeper.BankQuerier(mock)
|
||||||
|
_, gotErr := q(ctx, &wasmvmtypes.BankQuery{
|
||||||
|
AllDenomMetadata: &wasmvmtypes.AllDenomMetadataQuery{
|
||||||
|
Pagination: &wasmvmtypes.PageRequest{
|
||||||
|
Key: []byte("key"),
|
||||||
|
Limit: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, gotErr)
|
||||||
|
exp := &query.PageRequest{
|
||||||
|
Key: []byte("key"),
|
||||||
|
Limit: 10,
|
||||||
|
}
|
||||||
|
assert.Equal(t, exp, capturedPagination)
|
||||||
|
}
|
||||||
|
|
||||||
func TestContractInfoWasmQuerier(t *testing.T) {
|
func TestContractInfoWasmQuerier(t *testing.T) {
|
||||||
myValidContractAddr := keeper.RandomBech32AccountAddress(t)
|
myValidContractAddr := keeper.RandomBech32AccountAddress(t)
|
||||||
myCreatorAddr := keeper.RandomBech32AccountAddress(t)
|
myCreatorAddr := keeper.RandomBech32AccountAddress(t)
|
||||||
@@ -673,9 +801,11 @@ func (m mockWasmQueryKeeper) GetCodeInfo(ctx sdk.Context, codeID uint64) *types.
|
|||||||
}
|
}
|
||||||
|
|
||||||
type bankKeeperMock struct {
|
type bankKeeperMock struct {
|
||||||
GetSupplyFn func(ctx sdk.Context, denom string) sdk.Coin
|
GetSupplyFn func(ctx sdk.Context, denom string) sdk.Coin
|
||||||
GetBalanceFn func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
GetBalanceFn func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
||||||
GetAllBalancesFn func(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
GetAllBalancesFn func(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
||||||
|
GetDenomMetadataFn func(ctx sdk.Context, denom string) (banktypes.Metadata, bool)
|
||||||
|
GetDenomsMetadataFn func(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m bankKeeperMock) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
|
func (m bankKeeperMock) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
|
||||||
@@ -699,6 +829,20 @@ func (m bankKeeperMock) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk
|
|||||||
return m.GetAllBalancesFn(ctx, addr)
|
return m.GetAllBalancesFn(ctx, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m bankKeeperMock) GetDenomMetaData(ctx sdk.Context, denom string) (banktypes.Metadata, bool) {
|
||||||
|
if m.GetDenomMetadataFn == nil {
|
||||||
|
panic("not expected to be called")
|
||||||
|
}
|
||||||
|
return m.GetDenomMetadataFn(ctx, denom)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m bankKeeperMock) DenomsMetadata(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error) {
|
||||||
|
if m.GetDenomsMetadataFn == nil {
|
||||||
|
panic("not expected to be called")
|
||||||
|
}
|
||||||
|
return m.GetDenomsMetadataFn(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
func TestConvertProtoToJSONMarshal(t *testing.T) {
|
func TestConvertProtoToJSONMarshal(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
||||||
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
@@ -20,6 +21,8 @@ type BankViewKeeper interface {
|
|||||||
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
|
||||||
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
||||||
GetSupply(ctx sdk.Context, denom string) sdk.Coin
|
GetSupply(ctx sdk.Context, denom string) sdk.Coin
|
||||||
|
GetDenomMetaData(ctx sdk.Context, denom string) (banktypes.Metadata, bool)
|
||||||
|
DenomsMetadata(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Burner is a subset of the sdk bank keeper methods
|
// Burner is a subset of the sdk bank keeper methods
|
||||||
|
|||||||
Reference in New Issue
Block a user