Skip to content
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

Add AllDenomMetadata BankQuery #1426

Merged
merged 9 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ func AllCapabilities() []string {
"stargate",
"cosmwasm_1_1",
"cosmwasm_1_2",
"cosmwasm_1_3",
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/CosmWasm/wasmd
go 1.20

require (
github.com/CosmWasm/wasmvm v1.2.4
github.com/CosmWasm/wasmvm v1.3.0-rc.0
github.com/cosmos/cosmos-proto v1.0.0-beta.2
github.com/cosmos/cosmos-sdk v0.47.3
github.com/cosmos/gogogateway v1.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg=
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4=
github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ=
github.com/CosmWasm/wasmvm v1.2.4/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc=
github.com/CosmWasm/wasmvm v1.3.0-rc.0 h1:mHSFWM6i5HX/ZVzaFT0CmO0N4nnePJZX/DM4RNCP6uo=
github.com/CosmWasm/wasmvm v1.3.0-rc.0/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
Expand Down
71 changes: 69 additions & 2 deletions x/wasm/keeper/query_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ import (
"fmt"

errorsmod "cosmossdk.io/errors"
"github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
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"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"

"github.com/CosmWasm/wasmd/x/wasm/types"
)

type QueryHandler struct {
Expand Down Expand Up @@ -201,6 +202,27 @@ func BankQuerier(bankKeeper types.BankViewKeeper) func(ctx sdk.Context, request
}
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"}
}
}
Expand Down Expand Up @@ -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.
// 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.
Expand Down
150 changes: 147 additions & 3 deletions x/wasm/keeper/query_plugins_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -356,6 +357,133 @@ func TestBankQuerierBalance(t *testing.T) {
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
chipshort marked this conversation as resolved.
Show resolved Hide resolved
}
}}

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")
chipshort marked this conversation as resolved.
Show resolved Hide resolved
}

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)
}
chipshort marked this conversation as resolved.
Show resolved Hide resolved

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) {
myValidContractAddr := keeper.RandomBech32AccountAddress(t)
myCreatorAddr := keeper.RandomBech32AccountAddress(t)
Expand Down Expand Up @@ -673,9 +801,11 @@ func (m mockWasmQueryKeeper) GetCodeInfo(ctx sdk.Context, codeID uint64) *types.
}

type bankKeeperMock struct {
GetSupplyFn func(ctx sdk.Context, 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
GetSupplyFn func(ctx sdk.Context, 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
GetDenomMetadataFn func(ctx sdk.Context, denom string) (banktypes.Metadata, bool)
GetDenomsMetadataFn func(ctx context.Context, req *banktypes.QueryDenomsMetadataRequest) (*banktypes.QueryDenomsMetadataResponse, error)
chipshort marked this conversation as resolved.
Show resolved Hide resolved
}

func (m bankKeeperMock) GetSupply(ctx sdk.Context, denom string) sdk.Coin {
Expand All @@ -699,6 +829,20 @@ func (m bankKeeperMock) GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk
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) {
testCases := []struct {
name string
Expand Down
3 changes: 3 additions & 0 deletions x/wasm/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/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"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
Expand All @@ -20,6 +21,8 @@ type BankViewKeeper interface {
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
GetBalance(ctx sdk.Context, addr sdk.AccAddress, 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
Expand Down