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

feat: add batch operation for x/nft module #12187

Merged
merged 15 commits into from
Jun 15, 2022
38 changes: 36 additions & 2 deletions x/nft/keeper/nft.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ func (k Keeper) Mint(ctx sdk.Context, token nft.NFT, receiver sdk.AccAddress) er
return sdkerrors.Wrap(nft.ErrNFTExists, token.Id)
}

k.MintWithNoCheck(ctx, token, receiver)
return nil
}

// MintWithNoCheck defines a method for minting a new nft
// Note: this method does not check whether the class already exists in nft.
// The upper-layer application needs to check it when it needs to use it.
func (k Keeper) MintWithNoCheck(ctx sdk.Context, token nft.NFT, receiver sdk.AccAddress) {
k.setNFT(ctx, token)
k.setOwner(ctx, token.ClassId, token.Id, receiver)
k.incrTotalSupply(ctx, token.ClassId)
Expand All @@ -26,7 +34,6 @@ func (k Keeper) Mint(ctx sdk.Context, token nft.NFT, receiver sdk.AccAddress) er
Id: token.Id,
Owner: receiver.String(),
})
return nil
}

// Burn defines a method for burning a nft from a specific account.
Expand All @@ -40,6 +47,14 @@ func (k Keeper) Burn(ctx sdk.Context, classID string, nftID string) error {
return sdkerrors.Wrap(nft.ErrNFTNotExists, nftID)
}

k.BurnWithNoCheck(ctx, classID, nftID)
return nil
}

// BurnWithNoCheck defines a method for burning a nft from a specific account.
// Note: this method does not check whether the class already exists in nft.
// The upper-layer application needs to check it when it needs to use it
func (k Keeper) BurnWithNoCheck(ctx sdk.Context, classID string, nftID string) error {
dreamer-zq marked this conversation as resolved.
Show resolved Hide resolved
owner := k.GetOwner(ctx, classID, nftID)
nftStore := k.getNFTStore(ctx, classID)
nftStore.Delete([]byte(nftID))
Expand All @@ -64,10 +79,17 @@ func (k Keeper) Update(ctx sdk.Context, token nft.NFT) error {
if !k.HasNFT(ctx, token.ClassId, token.Id) {
return sdkerrors.Wrap(nft.ErrNFTNotExists, token.Id)
}
k.setNFT(ctx, token)
k.UpdateWithNoCheck(ctx, token)
return nil
}

// Update defines a method for updating an exist nft
// Note: this method does not check whether the class already exists in nft.
// The upper-layer application needs to check it when it needs to use it
func (k Keeper) UpdateWithNoCheck(ctx sdk.Context, token nft.NFT) {
k.setNFT(ctx, token)
}

// Transfer defines a method for sending a nft from one account to another account.
// Note: When the upper module uses this method, it needs to authenticate nft
func (k Keeper) Transfer(ctx sdk.Context,
Expand All @@ -83,6 +105,18 @@ func (k Keeper) Transfer(ctx sdk.Context,
return sdkerrors.Wrap(nft.ErrNFTNotExists, nftID)
}

k.TransferWithNoCheck(ctx, classID, nftID, receiver)
return nil
}

// Transfer defines a method for sending a nft from one account to another account.
// Note: this method does not check whether the class already exists in nft.
// The upper-layer application needs to check it when it needs to use it
func (k Keeper) TransferWithNoCheck(ctx sdk.Context,
classID string,
nftID string,
receiver sdk.AccAddress,
) error {
owner := k.GetOwner(ctx, classID, nftID)
k.deleteOwner(ctx, classID, nftID, owner)
k.setOwner(ctx, classID, nftID, receiver)
Expand Down
39 changes: 33 additions & 6 deletions x/nft/keeper/nft_batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,33 @@ func (k Keeper) BatchMint(ctx sdk.Context,
tokens []nft.NFT,
receiver sdk.AccAddress,
) error {
checked := make(map[string]bool, len(tokens))
for _, token := range tokens {
if err := k.Mint(ctx, token, receiver); err != nil {
return err
if !checked[token.ClassId] && !k.HasClass(ctx, token.ClassId) {
return sdkerrors.Wrap(nft.ErrClassNotExists, token.ClassId)
}

if k.HasNFT(ctx, token.ClassId, token.Id) {
return sdkerrors.Wrap(nft.ErrNFTExists, token.Id)
}

julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
checked[token.ClassId] = true
k.MintWithNoCheck(ctx, token, receiver)
}
return nil
}

// BatchBurn defines a method for burning a batch of nfts from a specific classID.
// Note: When the upper module uses this method, it needs to authenticate nft
func (k Keeper) BatchBurn(ctx sdk.Context, classID string, nftIDs []string) error {
if !k.HasClass(ctx, classID) {
return sdkerrors.Wrap(nft.ErrClassNotExists, classID)
}
for _, nftID := range nftIDs {
if err := k.Burn(ctx, classID, nftID); err != nil {
if !k.HasNFT(ctx, classID, nftID) {
return sdkerrors.Wrap(nft.ErrNFTNotExists, nftID)
}
if err := k.BurnWithNoCheck(ctx, classID, nftID); err != nil {
return err
}
}
Expand All @@ -33,10 +47,17 @@ func (k Keeper) BatchBurn(ctx sdk.Context, classID string, nftIDs []string) erro
// BatchUpdate defines a method for updating a batch of exist nfts
// Note: When the upper module uses this method, it needs to authenticate nft
func (k Keeper) BatchUpdate(ctx sdk.Context, tokens []nft.NFT) error {
checked := make(map[string]bool, len(tokens))
for _, token := range tokens {
if err := k.Update(ctx, token); err != nil {
return err
if !checked[token.ClassId] && !k.HasClass(ctx, token.ClassId) {
return sdkerrors.Wrap(nft.ErrClassNotExists, token.ClassId)
}

if !k.HasNFT(ctx, token.ClassId, token.Id) {
return sdkerrors.Wrap(nft.ErrNFTNotExists, token.Id)
}
checked[token.ClassId] = true
k.UpdateWithNoCheck(ctx, token)
}
return nil
}
Expand All @@ -48,8 +69,14 @@ func (k Keeper) BatchTransfer(ctx sdk.Context,
nftIDs []string,
receiver sdk.AccAddress,
) error {
if !k.HasClass(ctx, classID) {
return sdkerrors.Wrap(nft.ErrClassNotExists, classID)
}
for _, nftID := range nftIDs {
if err := k.Transfer(ctx, classID, nftID, receiver); err != nil {
if !k.HasNFT(ctx, classID, nftID) {
return sdkerrors.Wrap(nft.ErrNFTNotExists, nftID)
}
if err := k.TransferWithNoCheck(ctx, classID, nftID, receiver); err != nil {
return sdkerrors.Wrap(nft.ErrNFTNotExists, nftID)
}
}
Expand Down