code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/votes.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package sqlstore
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"strings"
    22  
    23  	"code.vegaprotocol.io/vega/datanode/entities"
    24  	"code.vegaprotocol.io/vega/datanode/metrics"
    25  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    26  
    27  	"github.com/georgysavva/scany/pgxscan"
    28  )
    29  
    30  type Votes struct {
    31  	*ConnectionSource
    32  }
    33  
    34  var votesOrdering = TableOrdering{
    35  	ColumnOrdering{Name: "vega_time", Sorting: ASC},
    36  }
    37  
    38  func NewVotes(connectionSource *ConnectionSource) *Votes {
    39  	d := &Votes{
    40  		ConnectionSource: connectionSource,
    41  	}
    42  	return d
    43  }
    44  
    45  func (vs *Votes) Add(ctx context.Context, v entities.Vote) error {
    46  	defer metrics.StartSQLQuery("Votes", "Add")()
    47  	_, err := vs.Exec(ctx,
    48  		`INSERT INTO votes(
    49  			proposal_id,
    50  			party_id,
    51  			value,
    52  			tx_hash,
    53  			vega_time,
    54  			initial_time,
    55  			total_governance_token_balance,
    56  			total_governance_token_weight,
    57  			total_equity_like_share_weight,
    58  			per_market_equity_like_share_weight
    59  		)
    60  		 VALUES ($1,  $2,  $3,  $4,  $5, $6, $7, $8, $9, $10)
    61  		 ON CONFLICT (proposal_id, party_id, vega_time) DO UPDATE SET
    62  			value = EXCLUDED.value,
    63  			total_governance_token_balance =EXCLUDED.total_governance_token_balance,
    64  			total_governance_token_weight = EXCLUDED.total_governance_token_weight,
    65  			total_equity_like_share_weight = EXCLUDED.total_equity_like_share_weight,
    66  			per_market_equity_like_share_weight = EXCLUDED.per_market_equity_like_share_weight,
    67  			tx_hash = EXCLUDED.tx_hash;
    68  		`,
    69  		v.ProposalID, v.PartyID, v.Value, v.TxHash, v.VegaTime, v.InitialTime,
    70  		v.TotalGovernanceTokenBalance, v.TotalGovernanceTokenWeight, v.TotalEquityLikeShareWeight, v.PerMarketEquityLikeShareWeight)
    71  	return err
    72  }
    73  
    74  func (vs *Votes) GetYesVotesForProposal(ctx context.Context, proposalIDStr string) ([]entities.Vote, error) {
    75  	defer metrics.StartSQLQuery("Votes", "GetYesVotesForProposal")()
    76  	yes := entities.VoteValueYes
    77  	return vs.Get(ctx, &proposalIDStr, nil, &yes)
    78  }
    79  
    80  func (vs *Votes) GetNoVotesForProposal(ctx context.Context, proposalIDStr string) ([]entities.Vote, error) {
    81  	defer metrics.StartSQLQuery("Votes", "GetNoVotesForProposal")()
    82  	no := entities.VoteValueNo
    83  	return vs.Get(ctx, &proposalIDStr, nil, &no)
    84  }
    85  
    86  func (vs *Votes) GetByParty(ctx context.Context, partyIDStr string) ([]entities.Vote, error) {
    87  	defer metrics.StartSQLQuery("Votes", "GetByParty")()
    88  	return vs.Get(ctx, nil, &partyIDStr, nil)
    89  }
    90  
    91  func (vs *Votes) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Vote, error) {
    92  	defer metrics.StartSQLQuery("Votes", "GetByTxHash")()
    93  
    94  	var votes []entities.Vote
    95  	query := `SELECT * FROM votes WHERE tx_hash = $1`
    96  	err := pgxscan.Select(ctx, vs.ConnectionSource, &votes, query, txHash)
    97  	if err != nil {
    98  		return nil, fmt.Errorf("querying votes: %w", err)
    99  	}
   100  	return votes, nil
   101  }
   102  
   103  func (vs *Votes) GetByPartyConnection(ctx context.Context, partyIDStr string, pagination entities.CursorPagination) ([]entities.Vote, entities.PageInfo, error) {
   104  	args := make([]interface{}, 0)
   105  	query := fmt.Sprintf(`select * from votes_current where party_id=%s`, nextBindVar(&args, entities.PartyID(partyIDStr)))
   106  
   107  	var (
   108  		votes    []entities.Vote
   109  		pageInfo entities.PageInfo
   110  		err      error
   111  	)
   112  
   113  	query, args, err = PaginateQuery[entities.VoteCursor](query, args, votesOrdering, pagination)
   114  	if err != nil {
   115  		return votes, pageInfo, err
   116  	}
   117  
   118  	if err = pgxscan.Select(ctx, vs.ConnectionSource, &votes, query, args...); err != nil {
   119  		return nil, entities.PageInfo{}, err
   120  	}
   121  
   122  	votes, pageInfo = entities.PageEntities[*v2.VoteEdge](votes, pagination)
   123  	return votes, pageInfo, nil
   124  }
   125  
   126  func (vs *Votes) GetConnection(
   127  	ctx context.Context,
   128  	proposalIDStr, partyIDStr *string,
   129  	pagination entities.CursorPagination,
   130  ) ([]entities.Vote, entities.PageInfo, error) {
   131  	query := `SELECT * FROM votes_current`
   132  	args := []interface{}{}
   133  
   134  	conditions := []string{}
   135  
   136  	if proposalIDStr != nil {
   137  		proposalID := entities.ProposalID(*proposalIDStr)
   138  		conditions = append(conditions, fmt.Sprintf("proposal_id=%s", nextBindVar(&args, proposalID)))
   139  	}
   140  
   141  	if partyIDStr != nil {
   142  		partyID := entities.PartyID(*partyIDStr)
   143  		conditions = append(conditions, fmt.Sprintf("party_id=%s", nextBindVar(&args, partyID)))
   144  	}
   145  
   146  	if len(conditions) > 0 {
   147  		query = fmt.Sprintf("%s WHERE %s", query, strings.Join(conditions, " AND "))
   148  	}
   149  
   150  	var (
   151  		votes    []entities.Vote
   152  		pageInfo entities.PageInfo
   153  		err      error
   154  	)
   155  
   156  	query, args, err = PaginateQuery[entities.VoteCursor](query, args, votesOrdering, pagination)
   157  	if err != nil {
   158  		return votes, pageInfo, err
   159  	}
   160  
   161  	if err = pgxscan.Select(ctx, vs.ConnectionSource, &votes, query, args...); err != nil {
   162  		return nil, entities.PageInfo{}, err
   163  	}
   164  
   165  	votes, pageInfo = entities.PageEntities[*v2.VoteEdge](votes, pagination)
   166  	return votes, pageInfo, nil
   167  }
   168  
   169  func (vs *Votes) Get(ctx context.Context,
   170  	proposalIDStr *string,
   171  	partyIDStr *string,
   172  	value *entities.VoteValue,
   173  ) ([]entities.Vote, error) {
   174  	query := `SELECT * FROM votes_current`
   175  	args := []interface{}{}
   176  
   177  	conditions := []string{}
   178  
   179  	if proposalIDStr != nil {
   180  		proposalID := entities.ProposalID(*proposalIDStr)
   181  		conditions = append(conditions, fmt.Sprintf("proposal_id=%s", nextBindVar(&args, proposalID)))
   182  	}
   183  
   184  	if partyIDStr != nil {
   185  		partyID := entities.PartyID(*partyIDStr)
   186  		conditions = append(conditions, fmt.Sprintf("party_id=%s", nextBindVar(&args, partyID)))
   187  	}
   188  
   189  	if value != nil {
   190  		conditions = append(conditions, fmt.Sprintf("value=%s", nextBindVar(&args, *value)))
   191  	}
   192  
   193  	if len(conditions) > 0 {
   194  		query = fmt.Sprintf("%s WHERE %s", query, strings.Join(conditions, " AND "))
   195  	}
   196  
   197  	votes := []entities.Vote{}
   198  	err := pgxscan.Select(ctx, vs.ConnectionSource, &votes, query, args...)
   199  	if err != nil {
   200  		return nil, fmt.Errorf("querying votes: %w", err)
   201  	}
   202  	return votes, nil
   203  }