code.vegaprotocol.io/vega@v0.79.0/core/activitystreak/activitiystreak_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 activitystreak
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"sort"
    22  
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	"code.vegaprotocol.io/vega/libs/num"
    25  	"code.vegaprotocol.io/vega/libs/proto"
    26  	"code.vegaprotocol.io/vega/logging"
    27  	snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1"
    28  )
    29  
    30  var ActivityStreakKey = (&types.PayloadActivityStreak{}).Key()
    31  
    32  type SnapshotEngine struct {
    33  	*Engine
    34  }
    35  
    36  func NewSnapshotEngine(
    37  	log *logging.Logger,
    38  	marketStats MarketsStatsAggregator,
    39  	broker Broker,
    40  ) *SnapshotEngine {
    41  	se := &SnapshotEngine{
    42  		Engine: New(log, marketStats, broker),
    43  	}
    44  
    45  	return se
    46  }
    47  
    48  func (e *SnapshotEngine) Namespace() types.SnapshotNamespace {
    49  	return types.ActivityStreakSnapshot
    50  }
    51  
    52  func (e *SnapshotEngine) Keys() []string {
    53  	return []string{ActivityStreakKey}
    54  }
    55  
    56  func (e *SnapshotEngine) Stopped() bool {
    57  	return false
    58  }
    59  
    60  func (e *SnapshotEngine) GetState(k string) ([]byte, []types.StateProvider, error) {
    61  	state, err := e.serialise(k)
    62  	return state, nil, err
    63  }
    64  
    65  func (e *SnapshotEngine) LoadState(_ context.Context, p *types.Payload) ([]types.StateProvider, error) {
    66  	if e.Namespace() != p.Data.Namespace() {
    67  		return nil, types.ErrInvalidSnapshotNamespace
    68  	}
    69  
    70  	switch data := p.Data.(type) {
    71  	case *types.PayloadActivityStreak:
    72  		e.loadStateFromSnapshot(data.ActivityStreak)
    73  		return nil, nil
    74  	default:
    75  		return nil, types.ErrUnknownSnapshotType
    76  	}
    77  }
    78  
    79  func (e *SnapshotEngine) loadStateFromSnapshot(state *snapshotpb.ActivityStreak) {
    80  	for _, v := range state.PartiesActivityStreak {
    81  		var rewardDistributionActivityMultiplier num.Decimal
    82  		if len(v.RewardDistributionMultiplier) > 0 {
    83  			rewardDistributionActivityMultiplier, _ = num.UnmarshalBinaryDecimal(v.RewardDistributionMultiplier)
    84  		}
    85  
    86  		var rewardVestingActivityMultiplier num.Decimal
    87  		if len(v.RewardVestingMultiplier) > 0 {
    88  			rewardVestingActivityMultiplier, _ = num.UnmarshalBinaryDecimal(v.RewardVestingMultiplier)
    89  		}
    90  
    91  		e.partiesActivity[v.Party] = &PartyActivity{
    92  			Active:                               v.Active,
    93  			Inactive:                             v.Inactive,
    94  			RewardDistributionActivityMultiplier: rewardDistributionActivityMultiplier,
    95  			RewardVestingActivityMultiplier:      rewardVestingActivityMultiplier,
    96  		}
    97  	}
    98  }
    99  
   100  func (e *SnapshotEngine) serialise(k string) ([]byte, error) {
   101  	switch k {
   102  	case ActivityStreakKey:
   103  		return e.serialiseAll()
   104  	default:
   105  		return nil, types.ErrSnapshotKeyDoesNotExist
   106  	}
   107  }
   108  
   109  func (e *SnapshotEngine) serialiseAll() ([]byte, error) {
   110  	out := snapshotpb.ActivityStreak{
   111  		PartiesActivityStreak: make([]*snapshotpb.PartyActivityStreak, 0, len(e.partiesActivity)),
   112  	}
   113  
   114  	for party, activity := range e.partiesActivity {
   115  		rewardDistributionMultiplier, _ := activity.RewardDistributionActivityMultiplier.MarshalBinary()
   116  		rewardVestingMultiplier, _ := activity.RewardVestingActivityMultiplier.MarshalBinary()
   117  		out.PartiesActivityStreak = append(out.PartiesActivityStreak, &snapshotpb.PartyActivityStreak{
   118  			Party:                        party,
   119  			Active:                       activity.Active,
   120  			Inactive:                     activity.Inactive,
   121  			RewardDistributionMultiplier: rewardDistributionMultiplier,
   122  			RewardVestingMultiplier:      rewardVestingMultiplier,
   123  		})
   124  	}
   125  
   126  	sort.Slice(out.PartiesActivityStreak, func(i, j int) bool {
   127  		return out.PartiesActivityStreak[i].Party < out.PartiesActivityStreak[j].Party
   128  	})
   129  
   130  	payload := &snapshotpb.Payload{
   131  		Data: &snapshotpb.Payload_ActivityStreak{
   132  			ActivityStreak: &out,
   133  		},
   134  	}
   135  
   136  	serialized, err := proto.Marshal(payload)
   137  	if err != nil {
   138  		return nil, fmt.Errorf("could not serialize team switches payload: %w", err)
   139  	}
   140  
   141  	return serialized, nil
   142  }