github.com/Finschia/finschia-sdk@v0.48.1/x/collection/keeper/send.go (about)

     1  package keeper
     2  
     3  import (
     4  	sdk "github.com/Finschia/finschia-sdk/types"
     5  	"github.com/Finschia/finschia-sdk/x/collection"
     6  )
     7  
     8  func (k Keeper) SendCoins(ctx sdk.Context, contractID string, from, to sdk.AccAddress, amount []collection.Coin) error {
     9  	if err := k.subtractCoins(ctx, contractID, from, amount); err != nil {
    10  		return err
    11  	}
    12  	k.addCoins(ctx, contractID, to, amount)
    13  
    14  	// legacy
    15  	for _, coin := range amount {
    16  		if err := collection.ValidateNFTID(coin.TokenId); err == nil {
    17  			k.iterateDescendants(ctx, contractID, coin.TokenId, func(descendantID string, _ int) (stop bool) {
    18  				event := collection.EventOwnerChanged{
    19  					ContractId: contractID,
    20  					TokenId:    descendantID,
    21  					From:       from.String(),
    22  					To:         to.String(),
    23  				}
    24  				if err := ctx.EventManager().EmitTypedEvent(&event); err != nil {
    25  					panic(err)
    26  				}
    27  				return false
    28  			})
    29  		}
    30  	}
    31  
    32  	return nil
    33  }
    34  
    35  func (k Keeper) addCoins(ctx sdk.Context, contractID string, address sdk.AccAddress, amount []collection.Coin) {
    36  	for _, coin := range amount {
    37  		balance := k.GetBalance(ctx, contractID, address, coin.TokenId)
    38  		newBalance := balance.Add(coin.Amount)
    39  		k.setBalance(ctx, contractID, address, coin.TokenId, newBalance)
    40  
    41  		if err := collection.ValidateNFTID(coin.TokenId); err == nil {
    42  			k.setOwner(ctx, contractID, coin.TokenId, address)
    43  		}
    44  	}
    45  }
    46  
    47  func (k Keeper) subtractCoins(ctx sdk.Context, contractID string, address sdk.AccAddress, amount []collection.Coin) error {
    48  	for _, coin := range amount {
    49  		balance := k.GetBalance(ctx, contractID, address, coin.TokenId)
    50  		newBalance := balance.Sub(coin.Amount)
    51  		if newBalance.IsNegative() {
    52  			return collection.ErrInsufficientToken.Wrapf("%s is smaller than %s", balance, coin.Amount)
    53  		}
    54  		k.setBalance(ctx, contractID, address, coin.TokenId, newBalance)
    55  
    56  		if err := collection.ValidateNFTID(coin.TokenId); err == nil {
    57  			k.deleteOwner(ctx, contractID, coin.TokenId)
    58  		}
    59  	}
    60  
    61  	return nil
    62  }
    63  
    64  func (k Keeper) GetBalance(ctx sdk.Context, contractID string, address sdk.AccAddress, tokenID string) sdk.Int {
    65  	store := ctx.KVStore(k.storeKey)
    66  	key := balanceKey(contractID, address, tokenID)
    67  	bz := store.Get(key)
    68  	if bz == nil {
    69  		return sdk.ZeroInt()
    70  	}
    71  
    72  	var balance sdk.Int
    73  	if err := balance.Unmarshal(bz); err != nil {
    74  		panic(err)
    75  	}
    76  	return balance
    77  }
    78  
    79  func (k Keeper) setBalance(ctx sdk.Context, contractID string, address sdk.AccAddress, tokenID string, balance sdk.Int) {
    80  	store := ctx.KVStore(k.storeKey)
    81  	key := balanceKey(contractID, address, tokenID)
    82  
    83  	if balance.IsZero() {
    84  		store.Delete(key)
    85  	} else {
    86  		bz, err := balance.Marshal()
    87  		if err != nil {
    88  			panic(err)
    89  		}
    90  		store.Set(key, bz)
    91  	}
    92  }
    93  
    94  func (k Keeper) AuthorizeOperator(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) error {
    95  	if _, err := k.GetContract(ctx, contractID); err != nil {
    96  		panic(err)
    97  	}
    98  
    99  	if _, err := k.GetAuthorization(ctx, contractID, holder, operator); err == nil {
   100  		return collection.ErrCollectionAlreadyApproved.Wrap("Already authorized")
   101  	}
   102  
   103  	k.setAuthorization(ctx, contractID, holder, operator)
   104  
   105  	return nil
   106  }
   107  
   108  func (k Keeper) RevokeOperator(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) error {
   109  	if _, err := k.GetAuthorization(ctx, contractID, holder, operator); err != nil {
   110  		return err
   111  	}
   112  
   113  	k.deleteAuthorization(ctx, contractID, holder, operator)
   114  	return nil
   115  }
   116  
   117  func (k Keeper) GetAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) (*collection.Authorization, error) {
   118  	store := ctx.KVStore(k.storeKey)
   119  	if store.Has(authorizationKey(contractID, operator, holder)) {
   120  		return &collection.Authorization{
   121  			Holder:   holder.String(),
   122  			Operator: operator.String(),
   123  		}, nil
   124  	}
   125  	return nil, collection.ErrCollectionNotApproved.Wrapf("no authorization by %s to %s", holder, operator)
   126  }
   127  
   128  func (k Keeper) setAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) {
   129  	store := ctx.KVStore(k.storeKey)
   130  	key := authorizationKey(contractID, operator, holder)
   131  	store.Set(key, []byte{})
   132  }
   133  
   134  func (k Keeper) deleteAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) {
   135  	store := ctx.KVStore(k.storeKey)
   136  	key := authorizationKey(contractID, operator, holder)
   137  	store.Delete(key)
   138  }