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 }