package nft import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/nft/internal/keeper" "github.com/cosmos/cosmos-sdk/x/nft/internal/types" ) // GenericHandler routes the messages to the handlers func GenericHandler(k keeper.Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { case types.MsgTransferNFT: return HandleMsgTransferNFT(ctx, msg, k) case types.MsgEditNFTMetadata: return HandleMsgEditNFTMetadata(ctx, msg, k) case types.MsgMintNFT: return HandleMsgMintNFT(ctx, msg, k) case types.MsgBurnNFT: return HandleMsgBurnNFT(ctx, msg, k) default: errMsg := fmt.Sprintf("unrecognized nft message type: %T", msg) return sdk.ErrUnknownRequest(errMsg).Result() } } } // HandleMsgTransferNFT handler for MsgTransferNFT func HandleMsgTransferNFT(ctx sdk.Context, msg types.MsgTransferNFT, k keeper.Keeper, ) sdk.Result { nft, err := k.GetNFT(ctx, msg.Denom, msg.ID) if err != nil { return err.Result() } // update NFT owner nft.SetOwner(msg.Recipient) // update the NFT (owners are updated within the keeper) err = k.UpdateNFT(ctx, msg.Denom, nft) if err != nil { return err.Result() } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTransfer, sdk.NewAttribute(types.AttributeKeyRecipient, msg.Recipient.String()), sdk.NewAttribute(types.AttributeKeyDenom, msg.Denom), sdk.NewAttribute(types.AttributeKeyNFTID, msg.ID), ), sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()), ), }) return sdk.Result{Events: ctx.EventManager().Events()} } // HandleMsgEditNFTMetadata handler for MsgEditNFTMetadata func HandleMsgEditNFTMetadata(ctx sdk.Context, msg types.MsgEditNFTMetadata, k keeper.Keeper, ) sdk.Result { nft, err := k.GetNFT(ctx, msg.Denom, msg.ID) if err != nil { return err.Result() } // update NFT nft.EditMetadata(msg.TokenURI) err = k.UpdateNFT(ctx, msg.Denom, nft) if err != nil { return err.Result() } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeEditNFTMetadata, sdk.NewAttribute(types.AttributeKeyDenom, msg.Denom), sdk.NewAttribute(types.AttributeKeyNFTID, msg.ID), sdk.NewAttribute(types.AttributeKeyNFTTokenURI, msg.TokenURI), ), sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()), ), }) return sdk.Result{Events: ctx.EventManager().Events()} } // HandleMsgMintNFT handles MsgMintNFT func HandleMsgMintNFT(ctx sdk.Context, msg types.MsgMintNFT, k keeper.Keeper, ) sdk.Result { nft := types.NewBaseNFT(msg.ID, msg.Recipient, msg.TokenURI) err := k.MintNFT(ctx, msg.Denom, &nft) if err != nil { return err.Result() } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeMintNFT, sdk.NewAttribute(types.AttributeKeyRecipient, msg.Recipient.String()), sdk.NewAttribute(types.AttributeKeyDenom, msg.Denom), sdk.NewAttribute(types.AttributeKeyNFTID, msg.ID), sdk.NewAttribute(types.AttributeKeyNFTTokenURI, msg.TokenURI), ), sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()), ), }) return sdk.Result{Events: ctx.EventManager().Events()} } // HandleMsgBurnNFT handles MsgBurnNFT func HandleMsgBurnNFT(ctx sdk.Context, msg types.MsgBurnNFT, k keeper.Keeper, ) sdk.Result { _, err := k.GetNFT(ctx, msg.Denom, msg.ID) if err != nil { return err.Result() } // remove NFT err = k.DeleteNFT(ctx, msg.Denom, msg.ID) if err != nil { return err.Result() } ctx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeBurnNFT, sdk.NewAttribute(types.AttributeKeyDenom, msg.Denom), sdk.NewAttribute(types.AttributeKeyNFTID, msg.ID), ), sdk.NewEvent( sdk.EventTypeMessage, sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender.String()), ), }) return sdk.Result{Events: ctx.EventManager().Events()} } // EndBlocker is run at the end of the block func EndBlocker(ctx sdk.Context, k keeper.Keeper) []abci.ValidatorUpdate { return nil }