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  }