github.com/DapperCollectives/CAST/backend@v0.0.0-20230921221157-1350c8be7c96/main/strategies/staked_token_weighted_default.go (about) 1 package strategies 2 3 import ( 4 "fmt" 5 "math" 6 7 "github.com/DapperCollectives/CAST/backend/main/models" 8 "github.com/DapperCollectives/CAST/backend/main/shared" 9 s "github.com/DapperCollectives/CAST/backend/main/shared" 10 "github.com/rs/zerolog/log" 11 ) 12 13 type StakedTokenWeightedDefault struct { 14 s.StrategyStruct 15 DB *s.Database 16 } 17 18 func (s *StakedTokenWeightedDefault) FetchBalance( 19 b *models.Balance, 20 p *models.Proposal, 21 ) (*models.Balance, error) { 22 23 var c models.Community 24 if err := c.GetCommunityByProposalId(s.DB, b.Proposal_id); err != nil { 25 return nil, err 26 } 27 28 strategy, err := models.MatchStrategyByProposal(*c.Strategies, *p.Strategy) 29 if err != nil { 30 log.Error().Err(err).Msg("Unable to find strategy for contract") 31 return nil, err 32 } 33 34 if err := s.FetchBalanceFromSnapshot(&strategy, b); err != nil { 35 log.Error().Err(err).Msg("Error calling snapshot client") 36 return nil, err 37 } 38 if err := b.CreateBalance(s.DB); err != nil { 39 log.Error().Err(err).Msg("Error creating balance in the database.") 40 return nil, err 41 } 42 43 return b, nil 44 } 45 46 func (s *StakedTokenWeightedDefault) FetchBalanceFromSnapshot( 47 strategy *models.Strategy, 48 b *models.Balance, 49 ) error { 50 51 var ftBalance = &shared.FTBalanceResponse{} 52 ftBalance.NewFTBalance() 53 54 if *strategy.Contract.Name == "FlowToken" { 55 if err := s.FlowAdapter.GetAddressBalanceAtBlockHeight( 56 b.Addr, 57 b.BlockHeight, 58 ftBalance, 59 &strategy.Contract, 60 ); err != nil { 61 log.Error().Err(err).Msg("Error fetching balance from snapshot client") 62 return err 63 } 64 b.PrimaryAccountBalance = ftBalance.PrimaryAccountBalance 65 b.SecondaryAccountBalance = ftBalance.SecondaryAccountBalance 66 b.StakingBalance = ftBalance.StakingBalance 67 68 } else { 69 if err := s.FlowAdapter.GetAddressBalanceAtBlockHeight( 70 b.Addr, 71 b.BlockHeight, 72 ftBalance, 73 &strategy.Contract, 74 ); err != nil { 75 log.Error().Err(err).Msg("Error fetching balance.") 76 return err 77 } 78 b.PrimaryAccountBalance = ftBalance.Balance 79 b.SecondaryAccountBalance = 0 80 b.StakingBalance = 0 81 } 82 83 return nil 84 } 85 func (s *StakedTokenWeightedDefault) TallyVotes( 86 votes []*models.VoteWithBalance, 87 r *models.ProposalResults, 88 p *models.Proposal, 89 ) (models.ProposalResults, error) { 90 var zero uint64 = 0 91 92 for _, vote := range votes { 93 if *vote.StakingBalance != zero { 94 var allowedBalance float64 95 96 if p.Max_weight != nil { 97 allowedBalance = p.EnforceMaxWeight(float64(*vote.StakingBalance)) 98 } else { 99 allowedBalance = float64(*vote.StakingBalance) 100 } 101 102 r.Results[vote.Choice] += int(allowedBalance) 103 r.Results_float[vote.Choice] += allowedBalance * math.Pow(10, -8) 104 } 105 } 106 107 return *r, nil 108 } 109 110 func (s *StakedTokenWeightedDefault) GetVoteWeightForBalance( 111 vote *models.VoteWithBalance, 112 proposal *models.Proposal, 113 ) (float64, error) { 114 var weight float64 115 var ERROR error = fmt.Errorf("no weight found, address: %s, strategy: %s", vote.Addr, *proposal.Strategy) 116 117 if vote.StakingBalance == nil { 118 return 0.00, nil 119 } 120 121 weight = float64(*vote.StakingBalance) * math.Pow(10, -8) 122 123 switch { 124 case proposal.Max_weight != nil && weight > *proposal.Max_weight: 125 weight = *proposal.Max_weight 126 return weight, nil 127 case proposal.Max_weight != nil && weight < *proposal.Max_weight: 128 return weight, nil 129 case weight > 0.00: 130 return weight, nil 131 case weight == 0.00: 132 return 0.00, nil 133 default: 134 return weight, ERROR 135 } 136 } 137 138 func (s *StakedTokenWeightedDefault) GetVotes( 139 votes []*models.VoteWithBalance, 140 proposal *models.Proposal, 141 ) ([]*models.VoteWithBalance, error) { 142 143 for _, vote := range votes { 144 weight, err := s.GetVoteWeightForBalance(vote, proposal) 145 if err != nil { 146 return nil, err 147 } 148 vote.Weight = &weight 149 } 150 151 return votes, nil 152 } 153 154 func (s *StakedTokenWeightedDefault) RequiresSnapshot() bool { 155 return true 156 } 157 158 func (s *StakedTokenWeightedDefault) InitStrategy( 159 f *shared.FlowAdapter, 160 db *shared.Database, 161 ) { 162 s.FlowAdapter = f 163 s.DB = db 164 }