feat(nft): add env bundler to nft module (#19367)

This commit is contained in:
samricotta 2024-02-08 13:19:31 +01:00 committed by GitHub
parent 195bd4ae65
commit 8de39661fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 54 additions and 37 deletions

View File

@ -401,7 +401,7 @@ func NewSimApp(
),
)
app.NFTKeeper = nftkeeper.NewKeeper(runtime.NewKVStoreService(keys[nftkeeper.StoreKey]), appCodec, app.AuthKeeper, app.BankKeeper)
app.NFTKeeper = nftkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[nftkeeper.StoreKey])), appCodec, app.AuthKeeper, app.BankKeeper)
// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(

View File

@ -35,4 +35,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#18355](https://github.com/cosmos/cosmos-sdk/pull/18355) Added new versions for `Balance`, `Owner`, `Supply`, `NFT`, `Class` queries that receives request via query string.
* [#19367](https://github.com/cosmos/cosmos-sdk/pull/19367) `appmodule.Environment` is received on the Keeper to get access to different application services
## [v0.1.0](https://github.com/cosmos/cosmos-sdk/releases/tag/x/nft/v0.1.0) - 2023-11-07

View File

@ -15,7 +15,7 @@ import (
var _ nft.QueryServer = Keeper{}
// Balance return the number of NFTs of a given class owned by the owner, same as balanceOf in ERC721
func (k Keeper) Balance(goCtx context.Context, r *nft.QueryBalanceRequest) (*nft.QueryBalanceResponse, error) {
func (k Keeper) Balance(ctx context.Context, r *nft.QueryBalanceRequest) (*nft.QueryBalanceResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -29,15 +29,14 @@ func (k Keeper) Balance(goCtx context.Context, r *nft.QueryBalanceRequest) (*nft
return nil, err
}
ctx := sdk.UnwrapSDKContext(goCtx)
balance := k.GetBalance(ctx, r.ClassId, owner)
return &nft.QueryBalanceResponse{Amount: balance}, nil
}
// BalanceByQueryString return the number of NFTs of a given class owned by the owner, same as balanceOf in ERC721
// but receives request via query string.
func (k Keeper) BalanceByQueryString(goCtx context.Context, r *nft.QueryBalanceByQueryStringRequest) (*nft.QueryBalanceByQueryStringResponse, error) {
res, err := k.Balance(goCtx, &nft.QueryBalanceRequest{
func (k Keeper) BalanceByQueryString(ctx context.Context, r *nft.QueryBalanceByQueryStringRequest) (*nft.QueryBalanceByQueryStringResponse, error) {
res, err := k.Balance(ctx, &nft.QueryBalanceRequest{
ClassId: r.ClassId,
Owner: r.Owner,
})
@ -48,7 +47,7 @@ func (k Keeper) BalanceByQueryString(goCtx context.Context, r *nft.QueryBalanceB
}
// Owner return the owner of the NFT based on its class and id, same as ownerOf in ERC721
func (k Keeper) Owner(goCtx context.Context, r *nft.QueryOwnerRequest) (*nft.QueryOwnerResponse, error) {
func (k Keeper) Owner(ctx context.Context, r *nft.QueryOwnerRequest) (*nft.QueryOwnerResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -61,7 +60,6 @@ func (k Keeper) Owner(goCtx context.Context, r *nft.QueryOwnerRequest) (*nft.Que
return nil, nft.ErrEmptyNFTID
}
ctx := sdk.UnwrapSDKContext(goCtx)
owner := k.GetOwner(ctx, r.ClassId, r.Id)
if owner.Empty() {
return &nft.QueryOwnerResponse{Owner: ""}, nil
@ -75,8 +73,8 @@ func (k Keeper) Owner(goCtx context.Context, r *nft.QueryOwnerRequest) (*nft.Que
// OwnerByQueryString return the owner of the NFT based on its class and id, same as ownerOf in ERC721
// but receives request via query string.
func (k Keeper) OwnerByQueryString(goCtx context.Context, r *nft.QueryOwnerByQueryStringRequest) (*nft.QueryOwnerByQueryStringResponse, error) {
res, err := k.Owner(goCtx, &nft.QueryOwnerRequest{
func (k Keeper) OwnerByQueryString(ctx context.Context, r *nft.QueryOwnerByQueryStringRequest) (*nft.QueryOwnerByQueryStringResponse, error) {
res, err := k.Owner(ctx, &nft.QueryOwnerRequest{
ClassId: r.ClassId,
Id: r.Id,
})
@ -87,7 +85,7 @@ func (k Keeper) OwnerByQueryString(goCtx context.Context, r *nft.QueryOwnerByQue
}
// Supply return the number of NFTs from the given class, same as totalSupply of ERC721.
func (k Keeper) Supply(goCtx context.Context, r *nft.QuerySupplyRequest) (*nft.QuerySupplyResponse, error) {
func (k Keeper) Supply(ctx context.Context, r *nft.QuerySupplyRequest) (*nft.QuerySupplyResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -95,15 +93,15 @@ func (k Keeper) Supply(goCtx context.Context, r *nft.QuerySupplyRequest) (*nft.Q
if len(r.ClassId) == 0 {
return nil, nft.ErrEmptyClassID
}
ctx := sdk.UnwrapSDKContext(goCtx)
supply := k.GetTotalSupply(ctx, r.ClassId)
return &nft.QuerySupplyResponse{Amount: supply}, nil
}
// SupplyByQueryString return the number of NFTs from the given class, same as totalSupply of ERC721.
// but receives request via query string.
func (k Keeper) SupplyByQueryString(goCtx context.Context, r *nft.QuerySupplyByQueryStringRequest) (*nft.QuerySupplyByQueryStringResponse, error) {
res, err := k.Supply(goCtx, &nft.QuerySupplyRequest{
func (k Keeper) SupplyByQueryString(ctx context.Context, r *nft.QuerySupplyByQueryStringRequest) (*nft.QuerySupplyByQueryStringResponse, error) {
res, err := k.Supply(ctx, &nft.QuerySupplyRequest{
ClassId: r.ClassId,
})
if err != nil {
@ -113,7 +111,7 @@ func (k Keeper) SupplyByQueryString(goCtx context.Context, r *nft.QuerySupplyByQ
}
// NFTs queries all NFTs of a given class or owner (at least one must be provided), similar to tokenByIndex in ERC721Enumerable
func (k Keeper) NFTs(goCtx context.Context, r *nft.QueryNFTsRequest) (*nft.QueryNFTsResponse, error) {
func (k Keeper) NFTs(ctx context.Context, r *nft.QueryNFTsRequest) (*nft.QueryNFTsResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -130,7 +128,6 @@ func (k Keeper) NFTs(goCtx context.Context, r *nft.QueryNFTsRequest) (*nft.Query
var nfts []*nft.NFT
var pageRes *query.PageResponse
ctx := sdk.UnwrapSDKContext(goCtx)
switch {
case len(r.ClassId) > 0 && len(r.Owner) > 0:
@ -175,7 +172,7 @@ func (k Keeper) NFTs(goCtx context.Context, r *nft.QueryNFTsRequest) (*nft.Query
}
// NFT return an NFT based on its class and id.
func (k Keeper) NFT(goCtx context.Context, r *nft.QueryNFTRequest) (*nft.QueryNFTResponse, error) {
func (k Keeper) NFT(ctx context.Context, r *nft.QueryNFTRequest) (*nft.QueryNFTResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -187,7 +184,6 @@ func (k Keeper) NFT(goCtx context.Context, r *nft.QueryNFTRequest) (*nft.QueryNF
return nil, nft.ErrEmptyNFTID
}
ctx := sdk.UnwrapSDKContext(goCtx)
n, has := k.GetNFT(ctx, r.ClassId, r.Id)
if !has {
return nil, nft.ErrNFTNotExists.Wrapf("not found nft: class: %s, id: %s", r.ClassId, r.Id)
@ -209,7 +205,7 @@ func (k Keeper) NFTByQueryString(goCtx context.Context, r *nft.QueryNFTByQuerySt
}
// Class return an NFT class based on its id
func (k Keeper) Class(goCtx context.Context, r *nft.QueryClassRequest) (*nft.QueryClassResponse, error) {
func (k Keeper) Class(ctx context.Context, r *nft.QueryClassRequest) (*nft.QueryClassResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
@ -218,7 +214,6 @@ func (k Keeper) Class(goCtx context.Context, r *nft.QueryClassRequest) (*nft.Que
return nil, nft.ErrEmptyClassID
}
ctx := sdk.UnwrapSDKContext(goCtx)
class, has := k.GetClass(ctx, r.ClassId)
if !has {
return nil, nft.ErrClassNotExists.Wrapf("not found class: %s", r.ClassId)
@ -228,8 +223,8 @@ func (k Keeper) Class(goCtx context.Context, r *nft.QueryClassRequest) (*nft.Que
// ClassByQueryString return an NFT class based on its id
// but receives request via query string.
func (k Keeper) ClassByQueryString(goCtx context.Context, r *nft.QueryClassByQueryStringRequest) (*nft.QueryClassByQueryStringResponse, error) {
res, err := k.Class(goCtx, &nft.QueryClassRequest{
func (k Keeper) ClassByQueryString(ctx context.Context, r *nft.QueryClassByQueryStringRequest) (*nft.QueryClassByQueryStringResponse, error) {
res, err := k.Class(ctx, &nft.QueryClassRequest{
ClassId: r.ClassId,
})
if err != nil {
@ -239,12 +234,11 @@ func (k Keeper) ClassByQueryString(goCtx context.Context, r *nft.QueryClassByQue
}
// Classes return all NFT classes
func (k Keeper) Classes(goCtx context.Context, r *nft.QueryClassesRequest) (*nft.QueryClassesResponse, error) {
func (k Keeper) Classes(ctx context.Context, r *nft.QueryClassesRequest) (*nft.QueryClassesResponse, error) {
if r == nil {
return nil, sdkerrors.ErrInvalidRequest.Wrap("empty request")
}
ctx := sdk.UnwrapSDKContext(goCtx)
store := k.storeService.OpenKVStore(ctx)
classStore := prefix.NewStore(runtime.KVStoreAdapter(store), ClassKey)

View File

@ -2,6 +2,8 @@ package keeper
import (
"cosmossdk.io/core/address"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/event"
store "cosmossdk.io/core/store"
"cosmossdk.io/x/nft"
@ -14,12 +16,15 @@ type Keeper struct {
storeService store.KVStoreService
bk nft.BankKeeper
ac address.Codec
eventService event.Service
}
// NewKeeper creates a new nft Keeper instance
func NewKeeper(storeService store.KVStoreService,
func NewKeeper(env appmodule.Environment,
cdc codec.BinaryCodec, ak nft.AccountKeeper, bk nft.BankKeeper,
) Keeper {
storeService := env.KVStoreService
// ensure nft module account is set
if addr := ak.GetModuleAddress(nft.ModuleName); addr == nil {
panic("the nft module account has not been set")
@ -28,6 +33,7 @@ func NewKeeper(storeService store.KVStoreService,
return Keeper{
cdc: cdc,
storeService: storeService,
eventService: env.EventService,
bk: bk,
ac: ak.AddressCodec(),
}

View File

@ -54,7 +54,6 @@ func (s *TestSuite) SetupTest() {
s.encCfg = moduletestutil.MakeTestEncodingConfig(module.AppModuleBasic{})
key := storetypes.NewKVStoreKey(nft.StoreKey)
storeService := runtime.NewKVStoreService(key)
testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
ctx := testCtx.Ctx.WithHeaderInfo(header.Info{Time: time.Now().Round(0).UTC()})
@ -73,7 +72,8 @@ func (s *TestSuite) SetupTest() {
s.accountKeeper = accountKeeper
nftKeeper := keeper.NewKeeper(storeService, s.encCfg.Codec, accountKeeper, bankKeeper)
env := runtime.NewEnvironment(runtime.NewKVStoreService(key))
nftKeeper := keeper.NewKeeper(env, s.encCfg.Codec, accountKeeper, bankKeeper)
queryHelper := baseapp.NewQueryServerTestHelper(ctx, s.encCfg.InterfaceRegistry)
nft.RegisterQueryServer(queryHelper, nftKeeper)

View File

@ -7,14 +7,13 @@ import (
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/x/nft"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
var _ nft.MsgServer = Keeper{}
// Send implements Send method of the types.MsgServer.
func (k Keeper) Send(goCtx context.Context, msg *nft.MsgSend) (*nft.MsgSendResponse, error) {
func (k Keeper) Send(ctx context.Context, msg *nft.MsgSend) (*nft.MsgSendResponse, error) {
if len(msg.ClassId) == 0 {
return nil, nft.ErrEmptyClassID
}
@ -33,7 +32,6 @@ func (k Keeper) Send(goCtx context.Context, msg *nft.MsgSend) (*nft.MsgSendRespo
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid receiver address (%s)", msg.Receiver)
}
ctx := sdk.UnwrapSDKContext(goCtx)
owner := k.GetOwner(ctx, msg.ClassId, msg.Id)
if !bytes.Equal(owner, sender) {
return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not the owner of nft %s", msg.Sender, msg.Id)
@ -43,14 +41,16 @@ func (k Keeper) Send(goCtx context.Context, msg *nft.MsgSend) (*nft.MsgSendRespo
return nil, err
}
err = ctx.EventManager().EmitTypedEvent(&nft.EventSend{
err = k.eventService.EventManager(ctx).Emit(&nft.EventSend{
ClassId: msg.ClassId,
Id: msg.Id,
Sender: msg.Sender,
Receiver: msg.Receiver,
})
if err != nil {
return nil, err
}
return &nft.MsgSendResponse{}, nil
}

View File

@ -36,11 +36,18 @@ func (k Keeper) mintWithNoCheck(ctx context.Context, token nft.NFT, receiver sdk
if err != nil {
return err
}
return sdk.UnwrapSDKContext(ctx).EventManager().EmitTypedEvent(&nft.EventMint{
err = k.eventService.EventManager(ctx).Emit(&nft.EventMint{
ClassId: token.ClassId,
Id: token.Id,
Owner: recStr,
})
if err != nil {
return err
}
return nil
}
// Burn defines a method for burning a nft from a specific account.
@ -71,16 +78,23 @@ func (k Keeper) burnWithNoCheck(ctx context.Context, classID, nftID string) erro
k.deleteOwner(ctx, classID, nftID, owner)
k.decrTotalSupply(ctx, classID)
ownerStr, err := k.ac.BytesToString(owner.Bytes())
if err != nil {
return err
}
return sdk.UnwrapSDKContext(ctx).EventManager().EmitTypedEvent(&nft.EventBurn{
err = k.eventService.EventManager(ctx).Emit(&nft.EventBurn{
ClassId: classID,
Id: nftID,
Owner: ownerStr,
})
if err != nil {
return err
}
return nil
}
// Update defines a method for updating an exist nft

View File

@ -3,7 +3,6 @@ package module
import (
modulev1 "cosmossdk.io/api/cosmos/nft/module/v1"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/core/store"
"cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig"
"cosmossdk.io/x/nft"
@ -27,9 +26,9 @@ func init() {
type ModuleInputs struct {
depinject.In
StoreService store.KVStoreService
Cdc codec.Codec
Registry cdctypes.InterfaceRegistry
Environment appmodule.Environment
Cdc codec.Codec
Registry cdctypes.InterfaceRegistry
AccountKeeper nft.AccountKeeper
BankKeeper nft.BankKeeper
@ -43,7 +42,7 @@ type ModuleOutputs struct {
}
func ProvideModule(in ModuleInputs) ModuleOutputs {
k := keeper.NewKeeper(in.StoreService, in.Cdc, in.AccountKeeper, in.BankKeeper)
k := keeper.NewKeeper(in.Environment, in.Cdc, in.AccountKeeper, in.BankKeeper)
m := NewAppModule(in.Cdc, k, in.AccountKeeper, in.BankKeeper, in.Registry)
return ModuleOutputs{NFTKeeper: k, Module: m}