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 }