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  }