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 }