code.vegaprotocol.io/vega@v0.79.0/datanode/entities/funding_period.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  	events "code.vegaprotocol.io/vega/protos/vega/events/v1"
    27  )
    28  
    29  type FundingPeriod struct {
    30  	MarketID         MarketID
    31  	FundingPeriodSeq uint64
    32  	StartTime        time.Time
    33  	EndTime          *time.Time
    34  	FundingPayment   *num.Decimal
    35  	FundingRate      *num.Decimal
    36  	ExternalTwap     *num.Decimal
    37  	InternalTwap     *num.Decimal
    38  	VegaTime         time.Time
    39  	TxHash           TxHash
    40  }
    41  
    42  func NewFundingPeriodFromProto(fp *events.FundingPeriod, txHash TxHash, vegaTime time.Time) (*FundingPeriod, error) {
    43  	fundingPeriod := &FundingPeriod{
    44  		MarketID:         MarketID(fp.MarketId),
    45  		FundingPeriodSeq: fp.Seq,
    46  		StartTime:        NanosToPostgresTimestamp(fp.Start),
    47  		VegaTime:         vegaTime,
    48  		TxHash:           txHash,
    49  	}
    50  
    51  	if fp.End != nil {
    52  		fundingPeriod.EndTime = ptr.From(NanosToPostgresTimestamp(*fp.End))
    53  	}
    54  
    55  	if fp.FundingPayment != nil {
    56  		fundingPayment, err := num.DecimalFromString(*fp.FundingPayment)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		fundingPeriod.FundingPayment = &fundingPayment
    61  	}
    62  
    63  	if fp.FundingRate != nil {
    64  		fundingRate, err := num.DecimalFromString(*fp.FundingRate)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  		fundingPeriod.FundingRate = &fundingRate
    69  	}
    70  
    71  	if fp.ExternalTwap != nil {
    72  		externalTwap, err := num.DecimalFromString(*fp.ExternalTwap)
    73  		if err != nil {
    74  			return nil, err
    75  		}
    76  		fundingPeriod.ExternalTwap = &externalTwap
    77  	}
    78  
    79  	if fp.InternalTwap != nil {
    80  		internalTwap, err := num.DecimalFromString(*fp.InternalTwap)
    81  		if err != nil {
    82  			return nil, err
    83  		}
    84  		fundingPeriod.InternalTwap = &internalTwap
    85  	}
    86  
    87  	return fundingPeriod, nil
    88  }
    89  
    90  func (fp FundingPeriod) ToProto() *events.FundingPeriod {
    91  	var (
    92  		endTime        *int64
    93  		fundingPayment *string
    94  		fundingRate    *string
    95  		externalTwap   *string
    96  		internalTwap   *string
    97  	)
    98  
    99  	if fp.EndTime != nil {
   100  		endTime = ptr.From(fp.EndTime.UnixNano())
   101  	}
   102  
   103  	if fp.FundingPayment != nil {
   104  		fundingPayment = ptr.From(fp.FundingPayment.String())
   105  	}
   106  
   107  	if fp.FundingRate != nil {
   108  		fundingRate = ptr.From(fp.FundingRate.String())
   109  	}
   110  
   111  	if fp.ExternalTwap != nil {
   112  		externalTwap = ptr.From(fp.ExternalTwap.String())
   113  	}
   114  
   115  	if fp.InternalTwap != nil {
   116  		internalTwap = ptr.From(fp.InternalTwap.String())
   117  	}
   118  
   119  	return &events.FundingPeriod{
   120  		MarketId:       fp.MarketID.String(),
   121  		Seq:            fp.FundingPeriodSeq,
   122  		Start:          fp.StartTime.UnixNano(),
   123  		End:            endTime,
   124  		FundingPayment: fundingPayment,
   125  		FundingRate:    fundingRate,
   126  		ExternalTwap:   externalTwap,
   127  		InternalTwap:   internalTwap,
   128  	}
   129  }
   130  
   131  func (fp FundingPeriod) Cursor() *Cursor {
   132  	pc := FundingPeriodCursor{
   133  		StartTime:        fp.StartTime,
   134  		MarketID:         fp.MarketID,
   135  		FundingPeriodSeq: fp.FundingPeriodSeq,
   136  	}
   137  
   138  	return NewCursor(pc.String())
   139  }
   140  
   141  func (fp FundingPeriod) ToProtoEdge(_ ...any) (*v2.FundingPeriodEdge, error) {
   142  	return &v2.FundingPeriodEdge{
   143  		Node:   fp.ToProto(),
   144  		Cursor: fp.Cursor().Encode(),
   145  	}, nil
   146  }
   147  
   148  type FundingPeriodDataPoint struct {
   149  	MarketID         MarketID
   150  	FundingPeriodSeq uint64
   151  	DataPointType    FundingPeriodDataPointSource
   152  	Price            num.Decimal
   153  	Twap             num.Decimal
   154  	Timestamp        time.Time
   155  	VegaTime         time.Time
   156  	TxHash           TxHash
   157  }
   158  
   159  func NewFundingPeriodDataPointFromProto(fpdp *events.FundingPeriodDataPoint, txHash TxHash, vegaTime time.Time) (*FundingPeriodDataPoint, error) {
   160  	price, err := num.DecimalFromString(fpdp.Price)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	twap, err := num.DecimalFromString(fpdp.Twap)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	return &FundingPeriodDataPoint{
   170  		MarketID:         MarketID(fpdp.MarketId),
   171  		FundingPeriodSeq: fpdp.Seq,
   172  		DataPointType:    FundingPeriodDataPointSource(fpdp.DataPointType),
   173  		Price:            price,
   174  		Twap:             twap,
   175  		Timestamp:        NanosToPostgresTimestamp(fpdp.Timestamp),
   176  		VegaTime:         vegaTime,
   177  		TxHash:           txHash,
   178  	}, nil
   179  }
   180  
   181  func (dp FundingPeriodDataPoint) ToProto() *events.FundingPeriodDataPoint {
   182  	return &events.FundingPeriodDataPoint{
   183  		MarketId:      dp.MarketID.String(),
   184  		Seq:           dp.FundingPeriodSeq,
   185  		DataPointType: events.FundingPeriodDataPoint_Source(dp.DataPointType),
   186  		Price:         dp.Price.String(),
   187  		Twap:          dp.Twap.String(),
   188  		Timestamp:     dp.Timestamp.UnixNano(),
   189  	}
   190  }
   191  
   192  func (dp FundingPeriodDataPoint) Cursor() *Cursor {
   193  	pc := FundingPeriodDataPointCursor{
   194  		Timestamp:        dp.Timestamp,
   195  		MarketID:         dp.MarketID,
   196  		FundingPeriodSeq: dp.FundingPeriodSeq,
   197  		DataPointType:    dp.DataPointType,
   198  	}
   199  
   200  	return NewCursor(pc.String())
   201  }
   202  
   203  func (dp FundingPeriodDataPoint) ToProtoEdge(_ ...any) (*v2.FundingPeriodDataPointEdge, error) {
   204  	return &v2.FundingPeriodDataPointEdge{
   205  		Node:   dp.ToProto(),
   206  		Cursor: dp.Cursor().Encode(),
   207  	}, nil
   208  }
   209  
   210  type FundingPeriodCursor struct {
   211  	// We're using start-time over vega-time for the cursor because the funding period record can be updated
   212  	// on settlement and the vega time and tx hash will change, but the start time will not.
   213  	StartTime        time.Time `json:"startTime"`
   214  	MarketID         MarketID  `json:"marketID"`
   215  	FundingPeriodSeq uint64    `json:"fundingPeriodSeq"`
   216  }
   217  
   218  func (c FundingPeriodCursor) String() string {
   219  	bs, err := json.Marshal(c)
   220  	if err != nil {
   221  		panic(fmt.Errorf("could not marshal funding period cursor: %w", err))
   222  	}
   223  	return string(bs)
   224  }
   225  
   226  func (c *FundingPeriodCursor) Parse(cursorString string) error {
   227  	if cursorString == "" {
   228  		return nil
   229  	}
   230  	return json.Unmarshal([]byte(cursorString), c)
   231  }
   232  
   233  type FundingPeriodDataPointCursor struct {
   234  	// We want to use the timestamp of the data point over the vega time for the cursor because the timestamp represents a
   235  	// point in time between the start time and end time of the funding period and it is also used for filtering
   236  	// results when querying via the API.
   237  	Timestamp        time.Time                    `json:"timestamp"`
   238  	MarketID         MarketID                     `json:"marketID"`
   239  	FundingPeriodSeq uint64                       `json:"fundingPeriodSeq"`
   240  	DataPointType    FundingPeriodDataPointSource `json:"dataPointType"`
   241  }
   242  
   243  func (c FundingPeriodDataPointCursor) String() string {
   244  	bs, err := json.Marshal(c)
   245  	if err != nil {
   246  		panic(fmt.Errorf("could not marshal funding period data point cursor: %w", err))
   247  	}
   248  	return string(bs)
   249  }
   250  
   251  func (c *FundingPeriodDataPointCursor) Parse(cursorString string) error {
   252  	if cursorString == "" {
   253  		return nil
   254  	}
   255  	return json.Unmarshal([]byte(cursorString), c)
   256  }