code.vegaprotocol.io/vega@v0.79.0/core/types/liquidation.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 types
    17  
    18  import (
    19  	"time"
    20  
    21  	"code.vegaprotocol.io/vega/libs/num"
    22  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    23  	snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    24  )
    25  
    26  type LiquidationStrategy struct {
    27  	DisposalTimeStep    time.Duration
    28  	DisposalFraction    num.Decimal
    29  	FullDisposalSize    uint64
    30  	MaxFractionConsumed num.Decimal
    31  	DisposalSlippage    num.Decimal // this has to be a pointer for the time being, with the need to default to 0.1
    32  }
    33  
    34  type LiquidationNode struct {
    35  	MarketID   string
    36  	NetworkPos int64
    37  	NextStep   time.Time
    38  	Config     *LiquidationStrategy
    39  }
    40  
    41  func (l *LiquidationNode) isPayload() {}
    42  
    43  func (l *LiquidationNode) plToProto() interface{} {
    44  	return &snapshot.Payload_Liquidation{
    45  		Liquidation: l.IntoProto(),
    46  	}
    47  }
    48  
    49  func (l *LiquidationNode) Namespace() SnapshotNamespace {
    50  	return LiquidationSnapshot
    51  }
    52  
    53  func (l *LiquidationNode) Key() string {
    54  	return l.MarketID
    55  }
    56  
    57  func (l *LiquidationNode) IntoProto() *snapshot.Liquidation {
    58  	var cfg *vegapb.LiquidationStrategy
    59  	if l.Config != nil {
    60  		cfg = l.Config.IntoProto()
    61  	}
    62  	var ns int64
    63  	if !l.NextStep.IsZero() {
    64  		ns = l.NextStep.UnixNano()
    65  	}
    66  	return &snapshot.Liquidation{
    67  		MarketId:   l.MarketID,
    68  		NetworkPos: l.NetworkPos,
    69  		NextStep:   ns,
    70  		Config:     cfg,
    71  	}
    72  }
    73  
    74  func PayloadLiquidationNodeFromProto(p *snapshot.Payload_Liquidation) *LiquidationNode {
    75  	// @NOTE this is here only for the protocol upgrade
    76  	if p.Liquidation.Config != nil && p.Liquidation.Config.DisposalSlippageRange == "" {
    77  		p.Liquidation.Config.DisposalSlippageRange = "0"
    78  	}
    79  	node, err := LiquidationSnapshotFromProto(p.Liquidation)
    80  	if err != nil {
    81  		// @TODO figure out what to do with this error
    82  		panic("invalid liquidation snapshot payload: " + err.Error())
    83  	}
    84  	return node
    85  }
    86  
    87  func LiquidationSnapshotFromProto(p *snapshot.Liquidation) (*LiquidationNode, error) {
    88  	var s *LiquidationStrategy
    89  	if p.Config != nil {
    90  		st, err := LiquidationStrategyFromProto(p.Config)
    91  		if err != nil {
    92  			return nil, err
    93  		}
    94  		s = st
    95  	}
    96  	var ns time.Time
    97  	if p.NextStep > 0 {
    98  		ns = time.Unix(0, p.NextStep)
    99  	}
   100  	return &LiquidationNode{
   101  		MarketID:   p.MarketId,
   102  		NetworkPos: p.NetworkPos,
   103  		NextStep:   ns,
   104  		Config:     s,
   105  	}, nil
   106  }
   107  
   108  func LiquidationStrategyFromProto(p *vegapb.LiquidationStrategy) (*LiquidationStrategy, error) {
   109  	df, err := num.DecimalFromString(p.DisposalFraction)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	mfc, err := num.DecimalFromString(p.MaxFractionConsumed)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	if p.DisposalSlippageRange == "" {
   118  		p.DisposalSlippageRange = "0"
   119  	}
   120  	slippage, err := num.DecimalFromString(p.DisposalSlippageRange)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	return &LiquidationStrategy{
   125  		DisposalTimeStep:    time.Second * time.Duration(p.DisposalTimeStep),
   126  		DisposalFraction:    df,
   127  		FullDisposalSize:    p.FullDisposalSize,
   128  		MaxFractionConsumed: mfc,
   129  		DisposalSlippage:    slippage,
   130  	}, nil
   131  }
   132  
   133  func (l *LiquidationStrategy) IntoProto() *vegapb.LiquidationStrategy {
   134  	slip := ""
   135  	if !l.DisposalSlippage.IsZero() {
   136  		slip = l.DisposalSlippage.String()
   137  	}
   138  	return &vegapb.LiquidationStrategy{
   139  		DisposalTimeStep:      int64(l.DisposalTimeStep / time.Second),
   140  		DisposalFraction:      l.DisposalFraction.String(),
   141  		FullDisposalSize:      l.FullDisposalSize,
   142  		MaxFractionConsumed:   l.MaxFractionConsumed.String(),
   143  		DisposalSlippageRange: slip,
   144  	}
   145  }
   146  
   147  func (l *LiquidationStrategy) DeepClone() *LiquidationStrategy {
   148  	cpy := *l
   149  	return &cpy
   150  }
   151  
   152  func (l *LiquidationStrategy) EQ(l2 *LiquidationStrategy) bool {
   153  	// if the memory address is the same, then they are obviously the same
   154  	if l == l2 {
   155  		return true
   156  	}
   157  	if l2 == nil {
   158  		return false
   159  	}
   160  	// this should be fine, there's no pointer fields to think about
   161  	// but just in case we end up switching the decimal types out
   162  	// return *l == *l2
   163  	return l.DisposalTimeStep == l2.DisposalTimeStep && l.FullDisposalSize == l2.FullDisposalSize &&
   164  		l.DisposalFraction.Equals(l2.DisposalFraction) && l.MaxFractionConsumed.Equals(l2.MaxFractionConsumed)
   165  }