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