code.vegaprotocol.io/vega@v0.79.0/core/products/perpetual_snapshot.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 products
    17  
    18  import (
    19  	"context"
    20  	"time"
    21  
    22  	"code.vegaprotocol.io/vega/core/types"
    23  	"code.vegaprotocol.io/vega/libs/num"
    24  	"code.vegaprotocol.io/vega/logging"
    25  	snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    26  )
    27  
    28  func NewCachedTWAPFromSnapshot(
    29  	log *logging.Logger,
    30  	t int64,
    31  	auctions *auctionIntervals,
    32  	state *snapshotpb.TWAPData,
    33  	points []*snapshotpb.DataPoint,
    34  ) *cachedTWAP {
    35  	sum, _ := num.UintFromString(state.SumProduct, 10)
    36  	c := &cachedTWAP{
    37  		log:         log,
    38  		periodStart: t,
    39  		start:       state.Start,
    40  		end:         state.End,
    41  		sumProduct:  sum,
    42  		auctions:    auctions,
    43  	}
    44  	c.points = make([]*dataPoint, 0, len(points))
    45  	for _, v := range points {
    46  		price, overflow := num.UintFromString(v.Price, 10)
    47  		if overflow {
    48  			log.Panic("invalid snapshot state in external data point", logging.String("price", v.Price), logging.Bool("overflow", overflow))
    49  		}
    50  		c.points = append(c.points, &dataPoint{price: price, t: v.Timestamp})
    51  	}
    52  	return c
    53  }
    54  
    55  func (c *cachedTWAP) serialise() *snapshotpb.TWAPData {
    56  	return &snapshotpb.TWAPData{
    57  		Start:      c.start,
    58  		End:        c.end,
    59  		SumProduct: c.sumProduct.String(),
    60  	}
    61  }
    62  
    63  func NewPerpetualFromSnapshot(
    64  	ctx context.Context,
    65  	log *logging.Logger,
    66  	p *types.Perps,
    67  	marketID string,
    68  	ts TimeService,
    69  	oe OracleEngine,
    70  	broker Broker,
    71  	state *snapshotpb.Perps,
    72  	assetDP uint32,
    73  ) (*Perpetual, error) {
    74  	// set next trigger from the settlement cue, it'll roll forward from `initial` to the next trigger time after `now`
    75  	tt := p.DataSourceSpecForSettlementSchedule.Data.GetInternalTimeTriggerSpecConfiguration()
    76  	tt.SetNextTrigger(ts.GetTimeNow().Truncate(time.Second))
    77  
    78  	perps, err := NewPerpetual(ctx, log, p, marketID, ts, oe, broker, assetDP)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	perps.startedAt = state.StartedAt
    84  	perps.seq = state.Seq
    85  
    86  	perps.auctions = &auctionIntervals{
    87  		auctionStart: state.AuctionIntervals.AuctionStart,
    88  		auctions:     state.AuctionIntervals.T,
    89  		total:        state.AuctionIntervals.Total,
    90  	}
    91  
    92  	perps.externalTWAP = NewCachedTWAPFromSnapshot(log, state.StartedAt, perps.auctions, state.ExternalTwapData, state.ExternalDataPoint)
    93  	perps.internalTWAP = NewCachedTWAPFromSnapshot(log, state.StartedAt, perps.auctions, state.InternalTwapData, state.InternalDataPoint)
    94  	return perps, nil
    95  }
    96  
    97  func (p *Perpetual) Serialize() *snapshotpb.Product {
    98  	perps := &snapshotpb.Perps{
    99  		Id:                p.id,
   100  		Seq:               p.seq,
   101  		StartedAt:         p.startedAt,
   102  		ExternalDataPoint: make([]*snapshotpb.DataPoint, 0, len(p.internalTWAP.points)),
   103  		InternalDataPoint: make([]*snapshotpb.DataPoint, 0, len(p.externalTWAP.points)),
   104  		AuctionIntervals: &snapshotpb.AuctionIntervals{
   105  			AuctionStart: p.auctions.auctionStart,
   106  			T:            p.auctions.auctions,
   107  			Total:        p.auctions.total,
   108  		},
   109  		ExternalTwapData: p.externalTWAP.serialise(),
   110  		InternalTwapData: p.internalTWAP.serialise(),
   111  	}
   112  
   113  	for _, v := range p.externalTWAP.points {
   114  		perps.ExternalDataPoint = append(perps.ExternalDataPoint, &snapshotpb.DataPoint{
   115  			Price:     v.price.String(),
   116  			Timestamp: v.t,
   117  		})
   118  	}
   119  
   120  	for _, v := range p.internalTWAP.points {
   121  		perps.InternalDataPoint = append(perps.InternalDataPoint, &snapshotpb.DataPoint{
   122  			Price:     v.price.String(),
   123  			Timestamp: v.t,
   124  		})
   125  	}
   126  	return &snapshotpb.Product{
   127  		Type: &snapshotpb.Product_Perps{
   128  			Perps: perps,
   129  		},
   130  	}
   131  }