code.vegaprotocol.io/vega@v0.79.0/datanode/entities/amm_pool.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 entities 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "time" 22 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/libs/ptr" 25 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 26 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 27 ) 28 29 type _AMMPoolID struct{} 30 31 type AMMPoolID = ID[_AMMPoolID] 32 33 type AMMPool struct { 34 ID AMMPoolID 35 PartyID PartyID 36 MarketID MarketID 37 AmmPartyID PartyID 38 Commitment num.Decimal 39 Status AMMStatus 40 StatusReason AMMStatusReason 41 ParametersBase num.Decimal 42 ParametersLowerBound *num.Decimal 43 ParametersUpperBound *num.Decimal 44 ParametersLeverageAtLowerBound *num.Decimal 45 ParametersLeverageAtUpperBound *num.Decimal 46 ProposedFee *num.Decimal 47 CreatedAt time.Time 48 LastUpdated time.Time 49 LowerVirtualLiquidity num.Decimal 50 LowerTheoreticalPosition num.Decimal 51 UpperVirtualLiquidity num.Decimal 52 UpperTheoreticalPosition num.Decimal 53 DataSourceID SpecID 54 MinimumPriceChangeTrigger num.Decimal 55 } 56 57 type AMMFilterType interface { 58 Where(fieldName *string, nextBindVar func(*[]any, any) string, args ...any) (string, []any) 59 } 60 61 type AMMPoolsFilter interface { 62 *PartyID | *MarketID | *AMMPoolID | *AMMStatus 63 64 // Where clause generated by the filter to be used in SQL queries. 65 // Optionally override the default field name defined on the implemented filter 66 // with the provided field name by providing a not nil value for the field name 67 Where(fieldName *string, nextBindVar func(*[]any, any) string, args ...any) (string, []any) 68 } 69 70 func AMMPoolFromProto(pool *eventspb.AMM, vegaTime time.Time) (AMMPool, error) { 71 var ( 72 parametersBase, 73 commitment num.Decimal 74 parametersLowerBound, 75 parametersUpperBound, fee *num.Decimal 76 err error 77 ) 78 partyID := PartyID(pool.PartyId) 79 marketID := MarketID(pool.MarketId) 80 poolID := AMMPoolID(pool.Id) 81 ammPartyID := PartyID(pool.AmmPartyId) 82 status := AMMStatus(pool.Status) 83 statusReason := AMMStatusReason(pool.StatusReason) 84 85 params := pool.Parameters 86 if params == nil { 87 return AMMPool{}, fmt.Errorf("missing AMM parameters") 88 } 89 90 if commitment, err = num.DecimalFromString(pool.Commitment); err != nil { 91 return AMMPool{}, err 92 } 93 94 if parametersBase, err = num.DecimalFromString(params.Base); err != nil { 95 return AMMPool{}, err 96 } 97 98 if params.LowerBound != nil { 99 v, err := num.DecimalFromString(*params.LowerBound) 100 if err != nil { 101 return AMMPool{}, err 102 } 103 parametersLowerBound = &v 104 } 105 106 if params.UpperBound != nil { 107 v, err := num.DecimalFromString(*params.UpperBound) 108 if err != nil { 109 return AMMPool{}, err 110 } 111 parametersUpperBound = &v 112 } 113 114 var lowerLeverage, upperLeverage *num.Decimal 115 if pool.Parameters.LeverageAtLowerBound != nil { 116 v, err := num.DecimalFromString(*pool.Parameters.LeverageAtLowerBound) 117 if err != nil { 118 return AMMPool{}, err 119 } 120 lowerLeverage = &v 121 } 122 123 if pool.Parameters.LeverageAtUpperBound != nil { 124 v, err := num.DecimalFromString(*pool.Parameters.LeverageAtUpperBound) 125 if err != nil { 126 return AMMPool{}, err 127 } 128 upperLeverage = &v 129 } 130 131 if len(pool.ProposedFee) > 0 { 132 fd, err := num.DecimalFromString(pool.ProposedFee) 133 if err != nil { 134 return AMMPool{}, err 135 } 136 fee = &fd 137 } 138 139 var lowerL, upperL, lowerPv, upperPv num.Decimal 140 if pool.LowerCurve != nil { 141 lowerL, err = num.DecimalFromString(pool.LowerCurve.VirtualLiquidity) 142 if err != nil { 143 return AMMPool{}, err 144 } 145 146 lowerPv, err = num.DecimalFromString(pool.LowerCurve.TheoreticalPosition) 147 if err != nil { 148 return AMMPool{}, err 149 } 150 } 151 152 if pool.UpperCurve != nil { 153 upperL, err = num.DecimalFromString(pool.UpperCurve.VirtualLiquidity) 154 if err != nil { 155 return AMMPool{}, err 156 } 157 158 upperPv, err = num.DecimalFromString(pool.UpperCurve.TheoreticalPosition) 159 if err != nil { 160 return AMMPool{}, err 161 } 162 } 163 164 minimumPriceChangeTrigger, err := num.DecimalFromString(pool.MinimumPriceChangeTrigger) 165 if err != nil { 166 return AMMPool{}, err 167 } 168 169 specID := SpecID("") 170 if pool.Parameters.DataSourceId != nil { 171 specID = SpecID(*pool.Parameters.DataSourceId) 172 } 173 174 return AMMPool{ 175 PartyID: partyID, 176 MarketID: marketID, 177 ID: poolID, 178 AmmPartyID: ammPartyID, 179 Commitment: commitment, 180 Status: status, 181 StatusReason: statusReason, 182 ParametersBase: parametersBase, 183 ParametersLowerBound: parametersLowerBound, 184 ParametersUpperBound: parametersUpperBound, 185 ParametersLeverageAtLowerBound: lowerLeverage, 186 ParametersLeverageAtUpperBound: upperLeverage, 187 ProposedFee: fee, 188 CreatedAt: vegaTime, 189 LastUpdated: vegaTime, 190 LowerVirtualLiquidity: lowerL, 191 LowerTheoreticalPosition: lowerPv, 192 UpperVirtualLiquidity: upperL, 193 UpperTheoreticalPosition: upperPv, 194 DataSourceID: specID, 195 MinimumPriceChangeTrigger: minimumPriceChangeTrigger, 196 }, nil 197 } 198 199 func (p AMMPool) ToProto() *eventspb.AMM { 200 var lowerBound, upperBound, lowerLeverage, upperLeverage *string 201 var fee string 202 203 if p.ParametersLowerBound != nil { 204 lowerBound = ptr.From(p.ParametersLowerBound.String()) 205 } 206 207 if p.ParametersUpperBound != nil { 208 upperBound = ptr.From(p.ParametersUpperBound.String()) 209 } 210 211 if p.ParametersLeverageAtLowerBound != nil { 212 lowerLeverage = ptr.From(p.ParametersLeverageAtLowerBound.String()) 213 } 214 215 if p.ParametersLeverageAtUpperBound != nil { 216 upperLeverage = ptr.From(p.ParametersLeverageAtUpperBound.String()) 217 } 218 if p.ProposedFee != nil { 219 fee = p.ProposedFee.String() 220 } 221 222 var specID *string 223 if p.DataSourceID.String() != "" { 224 specID = ptr.From((p.DataSourceID).String()) 225 } 226 227 return &eventspb.AMM{ 228 PartyId: p.PartyID.String(), 229 MarketId: p.MarketID.String(), 230 Id: p.ID.String(), 231 AmmPartyId: p.AmmPartyID.String(), 232 Commitment: p.Commitment.String(), 233 Status: eventspb.AMM_Status(p.Status), 234 StatusReason: eventspb.AMM_StatusReason(p.StatusReason), 235 ProposedFee: fee, 236 MinimumPriceChangeTrigger: p.MinimumPriceChangeTrigger.String(), 237 Parameters: &eventspb.AMM_ConcentratedLiquidityParameters{ 238 Base: p.ParametersBase.String(), 239 LowerBound: lowerBound, 240 UpperBound: upperBound, 241 LeverageAtLowerBound: lowerLeverage, 242 LeverageAtUpperBound: upperLeverage, 243 DataSourceId: specID, 244 }, 245 } 246 } 247 248 type AMMPoolCursor struct { 249 CreatedAt time.Time 250 PartyID PartyID 251 MarketID MarketID 252 ID AMMPoolID 253 AMMPartyID PartyID 254 } 255 256 func (c AMMPoolCursor) String() string { 257 bs, err := json.Marshal(c) 258 if err != nil { 259 panic(fmt.Errorf("could not marshal AMM pool cursor: %v", err)) 260 } 261 return string(bs) 262 } 263 264 func (c *AMMPoolCursor) Parse(cursorString string) error { 265 if cursorString == "" { 266 return nil 267 } 268 return json.Unmarshal([]byte(cursorString), c) 269 } 270 271 func (p AMMPool) Cursor() *Cursor { 272 pc := AMMPoolCursor{ 273 CreatedAt: p.CreatedAt, 274 PartyID: p.PartyID, 275 MarketID: p.MarketID, 276 ID: p.ID, 277 AMMPartyID: p.AmmPartyID, 278 } 279 return NewCursor(pc.String()) 280 } 281 282 func (p AMMPool) ToProtoEdge(_ ...any) (*v2.AMMEdge, error) { 283 return &v2.AMMEdge{ 284 Node: p.ToProto(), 285 Cursor: p.Cursor().Encode(), 286 }, nil 287 }