code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/assets.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  	"sync"
    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  var assetOrdering = TableOrdering{
    31  	ColumnOrdering{Name: "id", Sorting: ASC},
    32  }
    33  
    34  type Assets struct {
    35  	*ConnectionSource
    36  	cache     map[string]entities.Asset
    37  	cacheLock sync.Mutex
    38  }
    39  
    40  func NewAssets(connectionSource *ConnectionSource) *Assets {
    41  	a := &Assets{
    42  		ConnectionSource: connectionSource,
    43  		cache:            make(map[string]entities.Asset),
    44  	}
    45  	return a
    46  }
    47  
    48  func (as *Assets) Add(ctx context.Context, a entities.Asset) error {
    49  	defer metrics.StartSQLQuery("Assets", "Add")()
    50  	_, err := as.Exec(ctx,
    51  		`INSERT INTO assets(id, name, symbol, decimals, quantum, source, erc20_contract, lifetime_limit, withdraw_threshold, tx_hash, vega_time, status, chain_id)
    52  		 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
    53           ON CONFLICT (id, vega_time) DO UPDATE SET
    54              name = EXCLUDED.name,
    55              symbol = EXCLUDED.symbol,
    56              decimals = EXCLUDED.decimals,
    57              quantum = EXCLUDED.quantum,
    58              source = EXCLUDED.source,
    59              erc20_contract = EXCLUDED.erc20_contract,
    60              lifetime_limit = EXCLUDED.lifetime_limit,
    61              withdraw_threshold = EXCLUDED.withdraw_threshold,
    62  			tx_hash = EXCLUDED.tx_hash,
    63              vega_time = EXCLUDED.vega_time,
    64              status = EXCLUDED.status,
    65              chain_id = EXCLUDED.chain_id
    66              ;`,
    67  		a.ID,
    68  		a.Name,
    69  		a.Symbol,
    70  		a.Decimals,
    71  		a.Quantum,
    72  		a.Source,
    73  		a.ERC20Contract,
    74  		a.LifetimeLimit,
    75  		a.WithdrawThreshold,
    76  		a.TxHash,
    77  		a.VegaTime,
    78  		a.Status,
    79  		a.ChainID,
    80  	)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	as.AfterCommit(ctx, func() {
    86  		// delete cache
    87  		as.cacheLock.Lock()
    88  		defer as.cacheLock.Unlock()
    89  		delete(as.cache, a.ID.String())
    90  	})
    91  	return nil
    92  }
    93  
    94  func (as *Assets) GetByID(ctx context.Context, id string) (entities.Asset, error) {
    95  	as.cacheLock.Lock()
    96  	defer as.cacheLock.Unlock()
    97  
    98  	if asset, ok := as.cache[id]; ok {
    99  		return asset, nil
   100  	}
   101  
   102  	a := entities.Asset{}
   103  
   104  	defer metrics.StartSQLQuery("Assets", "GetByID")()
   105  	err := pgxscan.Get(ctx, as.ConnectionSource, &a,
   106  		getAssetQuery(ctx)+` WHERE id=$1`,
   107  		entities.AssetID(id))
   108  
   109  	if err == nil {
   110  		as.cache[id] = a
   111  	}
   112  	return a, as.wrapE(err)
   113  }
   114  
   115  func (as *Assets) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Asset, error) {
   116  	defer metrics.StartSQLQuery("Assets", "GetByTxHash")()
   117  
   118  	var assets []entities.Asset
   119  	err := pgxscan.Select(ctx, as.ConnectionSource, &assets, `SELECT * FROM assets WHERE tx_hash=$1`, txHash)
   120  	if err != nil {
   121  		return nil, as.wrapE(err)
   122  	}
   123  
   124  	return assets, nil
   125  }
   126  
   127  func (as *Assets) GetAll(ctx context.Context) ([]entities.Asset, error) {
   128  	assets := []entities.Asset{}
   129  	defer metrics.StartSQLQuery("Assets", "GetAll")()
   130  	err := pgxscan.Select(ctx, as.ConnectionSource, &assets, getAssetQuery(ctx))
   131  	return assets, err
   132  }
   133  
   134  func (as *Assets) GetAllWithCursorPagination(ctx context.Context, pagination entities.CursorPagination) (
   135  	[]entities.Asset, entities.PageInfo, error,
   136  ) {
   137  	var assets []entities.Asset
   138  	var pageInfo entities.PageInfo
   139  	var args []interface{}
   140  	var err error
   141  
   142  	query := getAssetQuery(ctx)
   143  	query, args, err = PaginateQuery[entities.AssetCursor](query, args, assetOrdering, pagination)
   144  	if err != nil {
   145  		return nil, pageInfo, err
   146  	}
   147  	defer metrics.StartSQLQuery("Assets", "GetAllWithCursorPagination")()
   148  
   149  	if err = pgxscan.Select(ctx, as.ConnectionSource, &assets, query, args...); err != nil {
   150  		return nil, pageInfo, fmt.Errorf("could not get assets: %w", err)
   151  	}
   152  
   153  	assets, pageInfo = entities.PageEntities[*v2.AssetEdge](assets, pagination)
   154  
   155  	return assets, pageInfo, nil
   156  }
   157  
   158  func getAssetQuery(_ context.Context) string {
   159  	return `SELECT * FROM assets_current`
   160  }