github.com/DapperCollectives/CAST/backend@v0.0.0-20230921221157-1350c8be7c96/main/strategies/balance_of_nfts.go (about) 1 package strategies 2 3 import ( 4 "github.com/DapperCollectives/CAST/backend/main/models" 5 "github.com/DapperCollectives/CAST/backend/main/shared" 6 "github.com/rs/zerolog/log" 7 ) 8 9 type BalanceOfNfts struct { 10 shared.StrategyStruct 11 DB *shared.Database 12 } 13 14 func (b *BalanceOfNfts) FetchBalance( 15 balance *models.Balance, 16 p *models.Proposal, 17 ) (*models.Balance, error) { 18 19 v := models.Vote{Proposal_id: balance.Proposal_id, Addr: balance.Addr} 20 vb := &models.VoteWithBalance{ 21 NFTs: []*models.NFT{}, 22 Vote: v, 23 } 24 25 var c models.Community 26 if err := c.GetCommunityByProposalId(b.DB, balance.Proposal_id); err != nil { 27 return nil, err 28 } 29 30 strategy, err := models.MatchStrategyByProposal(*c.Strategies, *p.Strategy) 31 if err != nil { 32 log.Error().Err(err).Msg("Unable to find strategy for contract.") 33 return nil, err 34 } 35 36 if err := b.queryNFTs(*vb, strategy, balance); err != nil { 37 return nil, err 38 } 39 40 return balance, nil 41 } 42 43 func (b *BalanceOfNfts) queryNFTs( 44 vb models.VoteWithBalance, 45 strategy models.Strategy, 46 balance *models.Balance, 47 ) error { 48 scriptPath := "./main/cadence/scripts/get_nfts_ids.cdc" 49 nftIds, err := b.FlowAdapter.GetNFTIds( 50 balance.Addr, 51 &strategy.Contract, 52 scriptPath, 53 ) 54 if err != nil { 55 return err 56 } 57 58 for _, nftId := range nftIds { 59 nft := &models.NFT{ 60 ID: nftId, 61 } 62 vb.NFTs = append(vb.NFTs, nft) 63 } 64 65 doesExist, err := models.DoesNFTExist(b.DB, &vb) 66 if err != nil { 67 return err 68 } 69 70 //only if the NFT ID is not already in the DB, 71 //do we add the balance 72 if !doesExist && err == nil { 73 err = models.CreateUserNFTRecord(b.DB, &vb) 74 balance.NFTCount = len(vb.NFTs) 75 } 76 77 return err 78 } 79 80 func (b *BalanceOfNfts) TallyVotes( 81 votes []*models.VoteWithBalance, 82 r *models.ProposalResults, 83 proposal *models.Proposal, 84 ) (models.ProposalResults, error) { 85 86 for _, vote := range votes { 87 if len(vote.NFTs) != 0 { 88 var voteWeight float64 89 90 voteWeight, err := b.GetVoteWeightForBalance(vote, proposal) 91 if err != nil { 92 return models.ProposalResults{}, err 93 } 94 95 r.Results[vote.Choice] += int(voteWeight) 96 r.Results_float[vote.Choice] += voteWeight 97 } 98 } 99 100 return *r, nil 101 } 102 103 func (b *BalanceOfNfts) GetVoteWeightForBalance(vote *models.VoteWithBalance, proposal *models.Proposal) (float64, error) { 104 nftIds, err := models.GetUserNFTs(b.DB, vote) 105 if err != nil { 106 log.Error().Err(err).Msg("error in GetVoteWeightForBalance for BalanceOfNFTs strategy") 107 return 0.00, err 108 } 109 110 if proposal.Max_weight != nil && float64(len(nftIds)) > *proposal.Max_weight { 111 return *proposal.Max_weight, nil 112 } 113 114 return float64(len(nftIds)), nil 115 } 116 117 func (b *BalanceOfNfts) GetVotes( 118 votes []*models.VoteWithBalance, 119 proposal *models.Proposal, 120 ) ([]*models.VoteWithBalance, error) { 121 for _, vote := range votes { 122 weight, err := b.GetVoteWeightForBalance(vote, proposal) 123 if err != nil { 124 return nil, err 125 } 126 vote.Weight = &weight 127 } 128 129 return votes, nil 130 } 131 132 func (b *BalanceOfNfts) RequiresSnapshot() bool { 133 return false 134 } 135 136 func (b *BalanceOfNfts) InitStrategy( 137 f *shared.FlowAdapter, 138 db *shared.Database, 139 ) { 140 b.FlowAdapter = f 141 b.DB = db 142 }