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  }