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 }