code.vegaprotocol.io/vega@v0.79.0/core/liquidity/target/spot/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 spot
    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/libs/proto"
    25  	snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    26  )
    27  
    28  func newTimestampedTotalStakeSnapshotFromProto(s *snapshot.TimestampedTotalStake) timestampedTotalStake {
    29  	return timestampedTotalStake{
    30  		Time:       time.Unix(0, s.Time),
    31  		TotalStake: s.TotalStake,
    32  	}
    33  }
    34  
    35  func (toi timestampedTotalStake) toSnapshotProto() *snapshot.TimestampedTotalStake {
    36  	return &snapshot.TimestampedTotalStake{
    37  		TotalStake: toi.TotalStake,
    38  		Time:       toi.Time.UnixNano(),
    39  	}
    40  }
    41  
    42  type SnapshotEngine struct {
    43  	*Engine
    44  	data    []byte
    45  	stopped bool
    46  	key     string
    47  	keys    []string
    48  }
    49  
    50  func NewSnapshotEngine(
    51  	parameters types.TargetStakeParameters,
    52  	marketID string,
    53  	positionFactor num.Decimal,
    54  ) *SnapshotEngine {
    55  	key := (&types.PayloadSpotLiquidityTarget{
    56  		Target: &snapshot.SpotLiquidityTarget{MarketId: marketID},
    57  	}).Key()
    58  
    59  	return &SnapshotEngine{
    60  		Engine: NewEngine(parameters, marketID, positionFactor),
    61  		key:    key,
    62  		keys:   []string{key},
    63  	}
    64  }
    65  
    66  func (e *SnapshotEngine) UpdateParameters(parameters types.TargetStakeParameters) {
    67  	e.Engine.UpdateParameters(parameters)
    68  }
    69  
    70  func (e *SnapshotEngine) StopSnapshots() {
    71  	e.stopped = true
    72  }
    73  
    74  func (e *SnapshotEngine) RecordTotalStake(oi uint64, now time.Time) error {
    75  	if err := e.Engine.RecordTotalStake(oi, now); err != nil {
    76  		return err
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  func (e *SnapshotEngine) GetTargetStake(now time.Time) *num.Uint {
    83  	return e.Engine.GetTargetStake(now)
    84  }
    85  
    86  func (e *SnapshotEngine) Namespace() types.SnapshotNamespace {
    87  	return types.LiquidityTargetSnapshot
    88  }
    89  
    90  func (e *SnapshotEngine) Keys() []string {
    91  	return e.keys
    92  }
    93  
    94  func (e *SnapshotEngine) Stopped() bool {
    95  	return e.stopped
    96  }
    97  
    98  func (e *SnapshotEngine) GetState(k string) ([]byte, []types.StateProvider, error) {
    99  	if k != e.key {
   100  		return nil, nil, types.ErrSnapshotKeyDoesNotExist
   101  	}
   102  
   103  	state, err := e.serialise()
   104  	return state, nil, err
   105  }
   106  
   107  func (e *SnapshotEngine) LoadState(_ context.Context, payload *types.Payload) ([]types.StateProvider, error) {
   108  	if e.Namespace() != payload.Data.Namespace() {
   109  		return nil, types.ErrInvalidSnapshotNamespace
   110  	}
   111  
   112  	switch pl := payload.Data.(type) {
   113  	case *types.PayloadSpotLiquidityTarget:
   114  
   115  		// Check the payload is for this market
   116  		if e.marketID != pl.Target.MarketId {
   117  			return nil, types.ErrUnknownSnapshotType
   118  		}
   119  
   120  		e.now = time.Unix(0, pl.Target.CurrentTime)
   121  		e.scheduledTruncate = time.Unix(0, pl.Target.ScheduledTruncate)
   122  		e.current = pl.Target.CurrentTotalStake
   123  		e.previous = make([]timestampedTotalStake, 0, len(pl.Target.PreviousTotalStake))
   124  		e.max = newTimestampedTotalStakeSnapshotFromProto(pl.Target.MaxTotalStake)
   125  
   126  		for _, poi := range pl.Target.PreviousTotalStake {
   127  			e.previous = append(e.previous, newTimestampedTotalStakeSnapshotFromProto(poi))
   128  		}
   129  
   130  		var err error
   131  		e.data, err = proto.Marshal(payload.IntoProto())
   132  		return nil, err
   133  
   134  	default:
   135  		return nil, types.ErrUnknownSnapshotType
   136  	}
   137  }
   138  
   139  func (e *SnapshotEngine) serialisePrevious() []*snapshot.TimestampedTotalStake {
   140  	poi := make([]*snapshot.TimestampedTotalStake, 0, len(e.previous))
   141  	for _, p := range e.previous {
   142  		poi = append(poi, p.toSnapshotProto())
   143  	}
   144  	return poi
   145  }
   146  
   147  // serialise marshal the snapshot state, populating the data fields
   148  // with updated values.
   149  func (e *SnapshotEngine) serialise() ([]byte, error) {
   150  	if e.stopped {
   151  		return nil, nil
   152  	}
   153  
   154  	p := &snapshot.Payload{
   155  		Data: &snapshot.Payload_SpotLiquidityTarget{
   156  			SpotLiquidityTarget: &snapshot.SpotLiquidityTarget{
   157  				MarketId:           e.marketID,
   158  				CurrentTime:        e.now.UnixNano(),
   159  				ScheduledTruncate:  e.scheduledTruncate.UnixNano(),
   160  				CurrentTotalStake:  e.current,
   161  				PreviousTotalStake: e.serialisePrevious(),
   162  				MaxTotalStake:      e.max.toSnapshotProto(),
   163  			},
   164  		},
   165  	}
   166  
   167  	var err error
   168  	e.data, err = proto.Marshal(p)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	return e.data, nil
   173  }