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

     1  package keeper
     2  
     3  import (
     4  	sdk "github.com/Finschia/finschia-sdk/types"
     5  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     6  	"github.com/Finschia/finschia-sdk/x/token"
     7  )
     8  
     9  func (k Keeper) Send(ctx sdk.Context, contractID string, from, to sdk.AccAddress, amount sdk.Int) error {
    10  	if !amount.IsPositive() {
    11  		panic(sdkerrors.ErrInvalidRequest.Wrap("amount must be positive"))
    12  	}
    13  
    14  	if err := k.subtractToken(ctx, contractID, from, amount); err != nil {
    15  		return err
    16  	}
    17  	k.addToken(ctx, contractID, to, amount)
    18  
    19  	return nil
    20  }
    21  
    22  func (k Keeper) AuthorizeOperator(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) error {
    23  	if _, err := k.GetClass(ctx, contractID); err != nil {
    24  		panic(err)
    25  	}
    26  
    27  	if _, err := k.GetAuthorization(ctx, contractID, holder, operator); err == nil {
    28  		return token.ErrTokenAlreadyApproved.Wrap("Already authorized")
    29  	}
    30  
    31  	k.setAuthorization(ctx, contractID, holder, operator)
    32  
    33  	return nil
    34  }
    35  
    36  func (k Keeper) RevokeOperator(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) error {
    37  	if _, err := k.GetAuthorization(ctx, contractID, holder, operator); err != nil {
    38  		return err
    39  	}
    40  
    41  	k.deleteAuthorization(ctx, contractID, holder, operator)
    42  	return nil
    43  }
    44  
    45  func (k Keeper) GetAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) (*token.Authorization, error) {
    46  	store := ctx.KVStore(k.storeKey)
    47  	if store.Has(authorizationKey(contractID, operator, holder)) {
    48  		return &token.Authorization{
    49  			Holder:   holder.String(),
    50  			Operator: operator.String(),
    51  		}, nil
    52  	}
    53  	return nil, token.ErrTokenNotApproved.Wrapf("no authorization to %s by %s", operator, holder)
    54  }
    55  
    56  func (k Keeper) setAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) {
    57  	store := ctx.KVStore(k.storeKey)
    58  	key := authorizationKey(contractID, operator, holder)
    59  	store.Set(key, []byte{})
    60  }
    61  
    62  func (k Keeper) deleteAuthorization(ctx sdk.Context, contractID string, holder, operator sdk.AccAddress) {
    63  	store := ctx.KVStore(k.storeKey)
    64  	key := authorizationKey(contractID, operator, holder)
    65  	store.Delete(key)
    66  }
    67  
    68  func (k Keeper) subtractToken(ctx sdk.Context, contractID string, addr sdk.AccAddress, amount sdk.Int) error {
    69  	balance := k.GetBalance(ctx, contractID, addr)
    70  	newBalance := balance.Sub(amount)
    71  	if newBalance.IsNegative() {
    72  		// Daphne emits ErrInsufficientFunds here, which is against to the spec.
    73  		return token.ErrInsufficientBalance.Wrapf("%s is smaller than %s", balance, amount)
    74  	}
    75  
    76  	k.setBalance(ctx, contractID, addr, newBalance)
    77  
    78  	return nil
    79  }
    80  
    81  func (k Keeper) addToken(ctx sdk.Context, contractID string, addr sdk.AccAddress, amount sdk.Int) {
    82  	balance := k.GetBalance(ctx, contractID, addr)
    83  	newBalance := balance.Add(amount)
    84  
    85  	k.setBalance(ctx, contractID, addr, newBalance)
    86  }
    87  
    88  func (k Keeper) GetBalance(ctx sdk.Context, contractID string, addr sdk.AccAddress) sdk.Int {
    89  	store := ctx.KVStore(k.storeKey)
    90  	amount := sdk.ZeroInt()
    91  	bz := store.Get(balanceKey(contractID, addr))
    92  	if bz != nil {
    93  		if err := amount.Unmarshal(bz); err != nil {
    94  			panic(err)
    95  		}
    96  	}
    97  	return amount
    98  }
    99  
   100  // setBalance sets balance.
   101  // The caller must validate `balance`.
   102  func (k Keeper) setBalance(ctx sdk.Context, contractID string, addr sdk.AccAddress, balance sdk.Int) {
   103  	store := ctx.KVStore(k.storeKey)
   104  	key := balanceKey(contractID, addr)
   105  	if balance.IsZero() {
   106  		store.Delete(key)
   107  	} else {
   108  		bz, err := balance.Marshal()
   109  		if err != nil {
   110  			panic(err)
   111  		}
   112  		store.Set(key, bz)
   113  	}
   114  }