code.vegaprotocol.io/vega@v0.79.0/core/execution/common/pegged_orders.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package common 17 18 import ( 19 "context" 20 "sort" 21 22 "code.vegaprotocol.io/vega/core/events" 23 "code.vegaprotocol.io/vega/core/types" 24 "code.vegaprotocol.io/vega/libs/num" 25 "code.vegaprotocol.io/vega/logging" 26 ) 27 28 type PeggedOrders struct { 29 log *logging.Logger 30 timeService TimeService 31 // parked list 32 parked []*types.Order 33 isParked map[string]struct{} 34 } 35 36 func NewPeggedOrders(log *logging.Logger, ts TimeService) *PeggedOrders { 37 return &PeggedOrders{ 38 log: log, 39 timeService: ts, 40 parked: []*types.Order{}, 41 isParked: map[string]struct{}{}, 42 } 43 } 44 45 func NewPeggedOrdersFromSnapshot( 46 log *logging.Logger, 47 ts TimeService, 48 state *types.PeggedOrdersState, 49 ) *PeggedOrders { 50 p := NewPeggedOrders(log, ts) 51 p.parked = state.Parked 52 for _, v := range p.parked { 53 p.isParked[v.ID] = struct{}{} 54 } 55 return p 56 } 57 58 func (p *PeggedOrders) Changed() bool { 59 return true 60 } 61 62 func (p *PeggedOrders) Parked() []*types.Order { 63 return p.parked 64 } 65 66 func (p *PeggedOrders) GetState() *types.PeggedOrdersState { 67 parkedCopy := make([]*types.Order, 0, len(p.parked)) 68 for _, v := range p.parked { 69 parkedCopy = append(parkedCopy, v.Clone()) 70 } 71 72 return &types.PeggedOrdersState{ 73 Parked: parkedCopy, 74 } 75 } 76 77 func (p *PeggedOrders) IsParked(id string) bool { 78 _, parked := p.isParked[id] 79 return parked 80 } 81 82 func (p *PeggedOrders) Park(o *types.Order) { 83 o.UpdatedAt = p.timeService.GetTimeNow().UnixNano() 84 o.Status = types.OrderStatusParked 85 o.Price = num.UintZero() 86 o.OriginalPrice = nil 87 88 p.parked = append(p.parked, o) 89 p.isParked[o.ID] = struct{}{} 90 } 91 92 func (p *PeggedOrders) Unpark(oid string) { 93 for i, po := range p.parked { 94 if po.ID == oid { 95 // Remove item from slice 96 copy(p.parked[i:], p.parked[i+1:]) 97 p.parked[len(p.parked)-1] = nil 98 p.parked = p.parked[:len(p.parked)-1] 99 delete(p.isParked, oid) 100 return 101 } 102 } 103 } 104 105 func (p *PeggedOrders) GetParkedByID(id string) *types.Order { 106 for _, o := range p.parked { 107 if o.ID == id { 108 return o 109 } 110 } 111 return nil 112 } 113 114 func (p *PeggedOrders) AmendParked(amended *types.Order) { 115 for i, o := range p.parked { 116 if o.ID == amended.ID { 117 p.parked[i] = amended 118 return 119 } 120 } 121 122 p.log.Panic("tried to amend a non parked order from the parked list", logging.Order(amended)) 123 } 124 125 func (p *PeggedOrders) RemoveAllForParty( 126 ctx context.Context, party string, status types.OrderStatus, 127 ) (orders []*types.Order, evts []events.Event) { 128 n := 0 129 now := p.timeService.GetTimeNow().UnixNano() 130 131 // then we look at the parked and delete + create events 132 for _, o := range p.parked { 133 if o.Party == party /* && o.Status == types.Order_STATUS_PARKED */ { 134 o.UpdatedAt = now 135 o.Status = status 136 orders = append(orders, o) 137 evts = append(evts, events.NewOrderEvent(ctx, o)) 138 delete(p.isParked, o.ID) 139 continue 140 } 141 // here we insert back in the slice 142 p.parked[n] = o 143 n++ 144 } 145 p.parked = p.parked[:n] 146 147 return 148 } 149 150 func (p *PeggedOrders) EnterAuction(ctx context.Context) []events.Event { 151 var ( 152 n = 0 153 now = p.timeService.GetTimeNow().UnixNano() 154 evts = []events.Event{} 155 ) 156 157 for _, o := range p.parked { 158 if o.TimeInForce == types.OrderTimeInForceGFN { 159 o.UpdatedAt = now 160 o.Status = types.OrderStatusCancelled 161 evts = append(evts, events.NewOrderEvent(ctx, o)) 162 delete(p.isParked, o.ID) 163 continue 164 } 165 166 // here we insert back in the slice 167 p.parked[n] = o 168 n++ 169 } 170 171 p.parked = p.parked[:n] 172 173 return evts 174 } 175 176 func (p *PeggedOrders) GetParkedIDs() []string { 177 ids := make([]string, 0, len(p.parked)) 178 for _, v := range p.parked { 179 ids = append(ids, v.ID) 180 } 181 return ids 182 } 183 184 func (p *PeggedOrders) GetAllParkedForParty(party string) (orders []*types.Order) { 185 for _, order := range p.parked { 186 if order.Party == party { 187 orders = append(orders, order) 188 } 189 } 190 return 191 } 192 193 func (p *PeggedOrders) Settled() []*types.Order { 194 // now we can remove the pegged orders too 195 peggedOrders := make([]*types.Order, 0, len(p.parked)) 196 for _, v := range p.parked { 197 order := v.Clone() 198 order.Status = types.OrderStatusStopped 199 peggedOrders = append(peggedOrders, order) 200 } 201 sort.Slice(peggedOrders, func(i, j int) bool { 202 return peggedOrders[i].ID < peggedOrders[j].ID 203 }) 204 205 p.parked = nil 206 p.isParked = map[string]struct{}{} 207 return peggedOrders 208 } 209 210 func (p *PeggedOrders) GetParkedOrdersCount() int { 211 return len(p.isParked) 212 }