code.vegaprotocol.io/vega@v0.79.0/core/events/distressed_positions.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 events
    17  
    18  import (
    19  	"context"
    20  
    21  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    22  )
    23  
    24  // DistressedPositions contains the market and parties that needed to have their orders closed in order
    25  // to maintain their open positions on the market.
    26  type DistressedPositions struct {
    27  	*Base
    28  	dpIDs map[string]struct{}
    29  	spIDs map[string]struct{}
    30  
    31  	pb eventspb.DistressedPositions
    32  }
    33  
    34  func NewDistressedPositionsEvent(ctx context.Context, marketID string, dParties, sParties []string) *DistressedPositions {
    35  	dk := make(map[string]struct{}, len(dParties))
    36  	sk := make(map[string]struct{}, len(sParties))
    37  	ret := &DistressedPositions{
    38  		Base:  newBase(ctx, DistressedPositionsEvent),
    39  		dpIDs: dk,
    40  		spIDs: sk,
    41  		pb: eventspb.DistressedPositions{
    42  			MarketId:          marketID,
    43  			DistressedParties: make([]string, 0, len(dParties)),
    44  			SafeParties:       make([]string, 0, len(sParties)),
    45  		},
    46  	}
    47  	ret.AddDistressedParties(dParties...)
    48  	ret.AddSafeParties(sParties...)
    49  	return ret
    50  }
    51  
    52  func (d *DistressedPositions) AddDistressedParties(parties ...string) {
    53  	// ensure parties cannot be marked as both safe and distressed
    54  	d.rmSafe(parties)
    55  	for _, p := range parties {
    56  		// party already registered as distressed
    57  		if _, ok := d.dpIDs[p]; ok {
    58  			continue
    59  		}
    60  		// mark party as distressed, ensure we don't mark a party as both distressed and no-longer-distressed
    61  		d.dpIDs[p] = struct{}{}
    62  		d.pb.DistressedParties = append(d.pb.DistressedParties, p)
    63  	}
    64  }
    65  
    66  func (d *DistressedPositions) AddSafeParties(parties ...string) {
    67  	// ensure these parties aren't marked as distressed
    68  	d.rmDistressed(parties)
    69  	for _, p := range parties {
    70  		if _, ok := d.spIDs[p]; ok {
    71  			continue
    72  		}
    73  		d.spIDs[p] = struct{}{}
    74  		d.pb.SafeParties = append(d.pb.SafeParties, p)
    75  	}
    76  }
    77  
    78  func (d DistressedPositions) MarketID() string {
    79  	return d.pb.MarketId
    80  }
    81  
    82  func (d *DistressedPositions) rmSafe(parties []string) {
    83  	for _, p := range parties {
    84  		if _, ok := d.spIDs[p]; ok {
    85  			delete(d.spIDs, p)
    86  			for i := 0; i < len(d.pb.SafeParties); i++ {
    87  				if d.pb.SafeParties[i] == p {
    88  					d.pb.SafeParties = append(d.pb.SafeParties[:i], d.pb.SafeParties[i+1:]...)
    89  					break
    90  				}
    91  			}
    92  		}
    93  	}
    94  }
    95  
    96  func (d *DistressedPositions) rmDistressed(parties []string) {
    97  	for _, p := range parties {
    98  		if _, ok := d.dpIDs[p]; ok {
    99  			delete(d.dpIDs, p)
   100  			for i := 0; i < len(d.pb.DistressedParties); i++ {
   101  				if d.pb.DistressedParties[i] == p {
   102  					d.pb.DistressedParties = append(d.pb.DistressedParties[:i], d.pb.DistressedParties[i+1:]...)
   103  					break
   104  				}
   105  			}
   106  		}
   107  	}
   108  }
   109  
   110  func (d DistressedPositions) DistressedParties() []string {
   111  	return d.pb.DistressedParties
   112  }
   113  
   114  func (d DistressedPositions) SafeParties() []string {
   115  	return d.pb.SafeParties
   116  }
   117  
   118  func (d DistressedPositions) IsMarket(marketID string) bool {
   119  	return d.pb.MarketId == marketID
   120  }
   121  
   122  func (d DistressedPositions) IsParty(partyID string) bool {
   123  	if _, ok := d.dpIDs[partyID]; ok {
   124  		return true
   125  	}
   126  	_, ok := d.spIDs[partyID]
   127  	return ok
   128  }
   129  
   130  func (d DistressedPositions) IsDistressedParty(p string) bool {
   131  	_, ok := d.dpIDs[p]
   132  	return ok
   133  }
   134  
   135  func (d DistressedPositions) IsSafeParty(p string) bool {
   136  	_, ok := d.spIDs[p]
   137  	return ok
   138  }
   139  
   140  func (d DistressedPositions) Proto() eventspb.DistressedPositions {
   141  	return d.pb
   142  }
   143  
   144  func (d DistressedPositions) StreamMessage() *eventspb.BusEvent {
   145  	busEvent := newBusEventFromBase(d.Base)
   146  	cpy := d.pb
   147  	busEvent.Event = &eventspb.BusEvent_DistressedPositions{
   148  		DistressedPositions: &cpy,
   149  	}
   150  
   151  	return busEvent
   152  }
   153  
   154  func (d DistressedPositions) StreamMarketMessage() *eventspb.BusEvent {
   155  	return d.StreamMessage()
   156  }
   157  
   158  func DistressedPositionsEventFromStream(ctx context.Context, be *eventspb.BusEvent) *DistressedPositions {
   159  	m := be.GetDistressedPositions()
   160  	dk := make(map[string]struct{}, len(m.DistressedParties))
   161  	for _, p := range m.DistressedParties {
   162  		dk[p] = struct{}{}
   163  	}
   164  	sk := make(map[string]struct{}, len(m.SafeParties))
   165  	for _, p := range m.SafeParties {
   166  		sk[p] = struct{}{}
   167  	}
   168  	return &DistressedPositions{
   169  		Base:  newBaseFromBusEvent(ctx, DistressedPositionsEvent, be),
   170  		dpIDs: dk,
   171  		spIDs: sk,
   172  		pb:    *m,
   173  	}
   174  }