github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/order/keeper/order.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 7 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 8 9 "github.com/fibonacci-chain/fbc/x/order/types" 10 token "github.com/fibonacci-chain/fbc/x/token/types" 11 ) 12 13 // TryPlaceOrder tries to charge fee & lock coins for a new order 14 func (k Keeper) TryPlaceOrder(ctx sdk.Context, order *types.Order) (fee sdk.SysCoins, err error) { 15 logger := ctx.Logger().With("module", "order") 16 // Trying to lock coins 17 needLockCoins := order.NeedLockCoins() 18 err = k.LockCoins(ctx, order.Sender, needLockCoins, token.LockCoinsTypeQuantity) 19 if err != nil { 20 logger.Info(fmt.Sprintf("place order failed: %v, %v", err, order)) 21 return fee, err 22 } 23 24 // charge fee for placing a new order 25 // Note: collected fees stored in cache, make sure handler will be succeed before updating cache 26 // Currently, after lock coins successfully, placeOrder will succeed if charging succeed 27 fee = GetOrderNewFee(order) 28 29 if err := k.LockCoins(ctx, order.Sender, fee, token.LockCoinsTypeFee); err != nil { 30 return fee, err 31 } 32 33 return fee, err 34 } 35 36 // PlaceOrder updates BlockOrderNum, DepthBook, execute TryPlaceOrder, and set the specified order to keeper 37 func (k Keeper) PlaceOrder(ctx sdk.Context, order *types.Order) error { 38 fee, err := k.TryPlaceOrder(ctx, order) 39 if err != nil { 40 return err 41 } 42 order.RecordOrderNewFee(fee) 43 k.AddFeeDetail(ctx, order.Sender, fee, types.FeeTypeOrderNew) 44 45 blockHeight := ctx.BlockHeight() 46 orderNum := k.GetBlockOrderNum(ctx, blockHeight) 47 order.OrderID = types.FormatOrderID(blockHeight, orderNum+1) 48 49 k.SetBlockOrderNum(ctx, blockHeight, orderNum+1) 50 k.SetOrder(ctx, order.OrderID, order) 51 52 // update depth book and orderIDsMap in cache 53 k.InsertOrderIntoDepthBook(order) 54 return nil 55 } 56 57 // ExpireOrder quits the specified order with the expired state 58 func (k Keeper) ExpireOrder(ctx sdk.Context, order *types.Order, logger log.Logger) { 59 k.quitOrder(ctx, order, types.FeeTypeOrderExpire, logger) 60 } 61 62 // CancelOrder quits the specified order with the canceled state 63 func (k Keeper) CancelOrder(ctx sdk.Context, order *types.Order, logger log.Logger) sdk.SysCoins { 64 return k.quitOrder(ctx, order, types.FeeTypeOrderCancel, logger) 65 } 66 67 // quitOrder unlocks & charges fee, unlocks coins, updates order, and updates DepthBook 68 func (k Keeper) quitOrder(ctx sdk.Context, order *types.Order, feeType string, logger log.Logger) (fee sdk.SysCoins) { 69 switch feeType { 70 case types.FeeTypeOrderCancel: 71 order.Cancel() 72 case types.FeeTypeOrderExpire: 73 order.Expire() 74 default: 75 return 76 } 77 78 // unlock coins in this order & charge fee 79 needUnlockCoins := order.NeedUnlockCoins() 80 k.UnlockCoins(ctx, order.Sender, needUnlockCoins, token.LockCoinsTypeQuantity) 81 82 lockedFee := GetOrderNewFee(order) 83 fee = GetOrderCostFee(order, ctx) 84 receiveFee := lockedFee.Sub(fee) 85 86 k.UnlockCoins(ctx, order.Sender, lockedFee, token.LockCoinsTypeFee) 87 k.AddFeeDetail(ctx, order.Sender, receiveFee, types.FeeTypeOrderReceive) 88 order.RecordOrderReceiveFee(receiveFee) 89 90 err := k.AddCollectedFees(ctx, fee, order.Sender, feeType, false) 91 92 if err != nil { 93 logger.Error(fmt.Sprintf("failed to charge order(%s) %s fee: %v", feeType, order.OrderID, err)) 94 } 95 96 order.Unlock() 97 k.SetOrder(ctx, order.OrderID, order) 98 99 // remove order from depth book cache 100 k.RemoveOrderFromDepthBook(order, feeType) 101 return fee 102 } 103 104 func (k Keeper) DropExpiredOrdersByBlockHeight(ctx sdk.Context, expiredBlockHeight int64) { 105 logger := ctx.Logger().With("module", "order") 106 store := ctx.KVStore(k.orderStoreKey) 107 iter := sdk.KVStorePrefixIterator(store, types.GetOrderKey(types.FormatOrderIDPrefix(expiredBlockHeight))) 108 defer iter.Close() 109 for ; iter.Valid(); iter.Next() { 110 var order types.Order 111 k.cdc.MustUnmarshalBinaryBare(iter.Value(), &order) 112 if order.Status == types.OrderStatusOpen && !k.IsProductLocked(ctx, order.Product) { 113 k.ExpireOrder(ctx, &order, logger) 114 logger.Info(fmt.Sprintf("order (%s) expired", order.OrderID)) 115 } 116 } 117 }