github.com/DapperCollectives/CAST/backend@v0.0.0-20230921221157-1350c8be7c96/main/strategies/custom_script.go (about)

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