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 }