feat(nft): add env bundler to nft module (#19367)
This commit is contained in:
parent
195bd4ae65
commit
8de39661fc
@ -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(
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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(),
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user