code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/parties.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  
    22  	"code.vegaprotocol.io/vega/datanode/entities"
    23  	"code.vegaprotocol.io/vega/datanode/metrics"
    24  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    25  
    26  	"github.com/georgysavva/scany/pgxscan"
    27  )
    28  
    29  var (
    30  	partiesOrdering = TableOrdering{
    31  		ColumnOrdering{Name: "vega_time", Sorting: ASC},
    32  		ColumnOrdering{Name: "id", Sorting: ASC},
    33  	}
    34  
    35  	partiesProfilesOrdering = TableOrdering{
    36  		ColumnOrdering{Name: "id", Sorting: ASC},
    37  	}
    38  )
    39  
    40  type Parties struct {
    41  	*ConnectionSource
    42  }
    43  
    44  func NewParties(connectionSource *ConnectionSource) *Parties {
    45  	ps := &Parties{
    46  		ConnectionSource: connectionSource,
    47  	}
    48  	return ps
    49  }
    50  
    51  // Initialise adds the built-in 'network' party which is never explicitly sent on the event
    52  // bus, but nonetheless is necessary.
    53  func (ps *Parties) Initialise(ctx context.Context) {
    54  	defer metrics.StartSQLQuery("Parties", "Initialise")()
    55  	_, err := ps.Exec(ctx,
    56  		`INSERT INTO parties(id, tx_hash, alias) VALUES ($1, $2, $3) ON CONFLICT (id) DO NOTHING`,
    57  		entities.PartyID("network"), entities.TxHash("01"), "network")
    58  	if err != nil {
    59  		panic(fmt.Errorf("unable to add built-in network party: %w", err))
    60  	}
    61  }
    62  
    63  func (ps *Parties) Add(ctx context.Context, p entities.Party) error {
    64  	defer metrics.StartSQLQuery("Parties", "Add")()
    65  	_, err := ps.Exec(ctx,
    66  		`INSERT INTO parties(id, tx_hash, vega_time)
    67  		 VALUES ($1, $2, $3)
    68  		 ON CONFLICT (id) DO NOTHING`,
    69  		p.ID,
    70  		p.TxHash,
    71  		p.VegaTime,
    72  	)
    73  	return err
    74  }
    75  
    76  func (ps *Parties) UpdateProfile(ctx context.Context, p *entities.PartyProfile) error {
    77  	defer metrics.StartSQLQuery("Parties", "Add")()
    78  	_, err := ps.Exec(ctx,
    79  		`UPDATE parties SET alias = $1, metadata = $2  WHERE id = $3`,
    80  		p.Alias,
    81  		p.Metadata,
    82  		p.PartyID,
    83  	)
    84  	return err
    85  }
    86  
    87  func (ps *Parties) ListProfiles(ctx context.Context, ids []string, pagination entities.CursorPagination) ([]entities.PartyProfile, entities.PageInfo, error) {
    88  	defer metrics.StartSQLQuery("Parties", "ListProfiles")()
    89  
    90  	profiles := make([]entities.PartyProfile, 0)
    91  	args := make([]interface{}, 0)
    92  
    93  	whereClause := ""
    94  	if len(ids) > 0 {
    95  		partyIDs := make([][]byte, len(ids))
    96  		for i, id := range ids {
    97  			partyID := entities.PartyID(id)
    98  			partyIDBytes, err := partyID.Bytes()
    99  			if err != nil {
   100  				return nil, entities.PageInfo{}, fmt.Errorf("invalid party ID found: %w", err)
   101  			}
   102  			partyIDs[i] = partyIDBytes
   103  		}
   104  		whereClause = fmt.Sprintf(" where id = ANY(%s)", nextBindVar(&args, partyIDs))
   105  	}
   106  
   107  	query := `SELECT id AS party_id, alias, metadata FROM parties` + whereClause
   108  
   109  	var pageInfo entities.PageInfo
   110  
   111  	query, args, err := PaginateQuery[entities.PartyProfile](query, args, partiesProfilesOrdering, pagination)
   112  	if err != nil {
   113  		return nil, pageInfo, err
   114  	}
   115  
   116  	if err := pgxscan.Select(ctx, ps.ConnectionSource, &profiles, query, args...); err != nil {
   117  		return nil, pageInfo, err
   118  	}
   119  
   120  	profiles, pageInfo = entities.PageEntities[*v2.PartyProfileEdge](profiles, pagination)
   121  	return profiles, pageInfo, nil
   122  }
   123  
   124  func (ps *Parties) GetByID(ctx context.Context, id string) (entities.Party, error) {
   125  	a := entities.Party{}
   126  	defer metrics.StartSQLQuery("Parties", "GetByID")()
   127  	err := pgxscan.Get(ctx, ps.ConnectionSource, &a,
   128  		`SELECT id, tx_hash, vega_time
   129  		 FROM parties WHERE id=$1`,
   130  		entities.PartyID(id))
   131  
   132  	return a, ps.wrapE(err)
   133  }
   134  
   135  func (ps *Parties) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Party, error) {
   136  	defer metrics.StartSQLQuery("Parties", "GetByTxHash")()
   137  
   138  	var parties []entities.Party
   139  	err := pgxscan.Select(ctx, ps.ConnectionSource, &parties, `SELECT id, tx_hash, vega_time FROM parties WHERE tx_hash=$1`, txHash)
   140  	if err != nil {
   141  		return nil, ps.wrapE(err)
   142  	}
   143  
   144  	return parties, nil
   145  }
   146  
   147  func (ps *Parties) GetAll(ctx context.Context) ([]entities.Party, error) {
   148  	parties := []entities.Party{}
   149  	defer metrics.StartSQLQuery("Parties", "GetAll")()
   150  	err := pgxscan.Select(ctx, ps.ConnectionSource, &parties, `
   151  		SELECT id, tx_hash, vega_time
   152  		FROM parties`)
   153  	return parties, err
   154  }
   155  
   156  func (ps *Parties) GetAllPaged(ctx context.Context, partyID string, pagination entities.CursorPagination) ([]entities.Party, entities.PageInfo, error) {
   157  	if partyID != "" {
   158  		party, err := ps.GetByID(ctx, partyID)
   159  		if err != nil {
   160  			return nil, entities.PageInfo{}, err
   161  		}
   162  
   163  		return []entities.Party{party}, entities.PageInfo{
   164  			HasNextPage:     false,
   165  			HasPreviousPage: false,
   166  			StartCursor:     party.Cursor().Encode(),
   167  			EndCursor:       party.Cursor().Encode(),
   168  		}, nil
   169  	}
   170  
   171  	parties := make([]entities.Party, 0)
   172  	args := make([]interface{}, 0)
   173  
   174  	query := `
   175  		SELECT id, tx_hash, vega_time
   176  		FROM parties
   177  	`
   178  
   179  	var pageInfo entities.PageInfo
   180  
   181  	query, args, err := PaginateQuery[entities.Party](query, args, partiesOrdering, pagination)
   182  	if err != nil {
   183  		return nil, pageInfo, err
   184  	}
   185  
   186  	if err := pgxscan.Select(ctx, ps.ConnectionSource, &parties, query, args...); err != nil {
   187  		return nil, pageInfo, err
   188  	}
   189  
   190  	parties, pageInfo = entities.PageEntities[*v2.PartyEdge](parties, pagination)
   191  	return parties, pageInfo, nil
   192  }