code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/deposits.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 type Deposits struct { 30 *ConnectionSource 31 } 32 33 const ( 34 sqlDepositsColumns = `id, status, party_id, asset, amount, foreign_tx_hash, 35 credited_timestamp, created_timestamp, tx_hash, vega_time` 36 37 depositsFilterDateColumn = "vega_time" 38 ) 39 40 var depositOrdering = TableOrdering{ 41 ColumnOrdering{Name: "vega_time", Sorting: ASC}, 42 ColumnOrdering{Name: "id", Sorting: ASC}, 43 } 44 45 func NewDeposits(connectionSource *ConnectionSource) *Deposits { 46 return &Deposits{ 47 ConnectionSource: connectionSource, 48 } 49 } 50 51 func (d *Deposits) Upsert(ctx context.Context, deposit *entities.Deposit) error { 52 query := fmt.Sprintf(`insert into deposits(%s) 53 values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) 54 on conflict (id, party_id, vega_time) do update 55 set 56 status=EXCLUDED.status, 57 asset=EXCLUDED.asset, 58 amount=EXCLUDED.amount, 59 foreign_tx_hash=EXCLUDED.foreign_tx_hash, 60 credited_timestamp=EXCLUDED.credited_timestamp, 61 created_timestamp=EXCLUDED.created_timestamp, 62 tx_hash=EXCLUDED.tx_hash`, sqlDepositsColumns) 63 64 defer metrics.StartSQLQuery("Deposits", "Upsert")() 65 if _, err := d.Exec(ctx, query, deposit.ID, deposit.Status, deposit.PartyID, deposit.Asset, deposit.Amount, 66 deposit.ForeignTxHash, deposit.CreditedTimestamp, deposit.CreatedTimestamp, deposit.TxHash, deposit.VegaTime); err != nil { 67 err = fmt.Errorf("could not insert deposit into database: %w", err) 68 return err 69 } 70 71 return nil 72 } 73 74 func (d *Deposits) GetByID(ctx context.Context, depositID string) (entities.Deposit, error) { 75 var deposit entities.Deposit 76 77 query := `select id, status, party_id, asset, amount, foreign_tx_hash, credited_timestamp, created_timestamp, tx_hash, vega_time 78 from deposits_current 79 where id = $1 80 order by id, party_id, vega_time desc` 81 82 defer metrics.StartSQLQuery("Deposits", "GetByID")() 83 return deposit, d.wrapE(pgxscan.Get( 84 ctx, d.ConnectionSource, &deposit, query, entities.DepositID(depositID))) 85 } 86 87 func (d *Deposits) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Deposit, error) { 88 defer metrics.StartSQLQuery("Deposits", "GetByTxHash")() 89 90 var deposits []entities.Deposit 91 query := fmt.Sprintf(`SELECT %s FROM deposits WHERE tx_hash = $1`, sqlDepositsColumns) 92 93 err := pgxscan.Select(ctx, d.ConnectionSource, &deposits, query, txHash) 94 if err != nil { 95 return nil, d.wrapE(err) 96 } 97 98 return deposits, nil 99 } 100 101 func (d *Deposits) GetByParty(ctx context.Context, party string, openOnly bool, pagination entities.Pagination, dateRange entities.DateRange) ( 102 []entities.Deposit, entities.PageInfo, error, 103 ) { 104 switch p := pagination.(type) { 105 case entities.CursorPagination: 106 return d.getByPartyCursorPagination(ctx, party, openOnly, p, dateRange) 107 default: 108 panic("unsupported pagination") 109 } 110 } 111 112 func (d *Deposits) getByPartyCursorPagination(ctx context.Context, party string, openOnly bool, 113 pagination entities.CursorPagination, dateRange entities.DateRange, 114 ) ([]entities.Deposit, entities.PageInfo, error) { 115 var deposits []entities.Deposit 116 var pageInfo entities.PageInfo 117 var err error 118 119 query, args := getDepositsByPartyQuery(party, dateRange) 120 if openOnly { 121 query = fmt.Sprintf(`%s and status = %s`, query, nextBindVar(&args, entities.DepositStatusOpen)) 122 } 123 query, args, err = PaginateQuery[entities.DepositCursor](query, args, depositOrdering, pagination) 124 if err != nil { 125 return nil, pageInfo, err 126 } 127 128 defer metrics.StartSQLQuery("Deposits", "GetByParty")() 129 if err = pgxscan.Select(ctx, d.ConnectionSource, &deposits, query, args...); err != nil { 130 return nil, pageInfo, fmt.Errorf("could not get deposits by party: %w", err) 131 } 132 133 deposits, pageInfo = entities.PageEntities[*v2.DepositEdge](deposits, pagination) 134 135 return deposits, pageInfo, nil 136 } 137 138 func getDepositsByPartyQuery(party string, dateRange entities.DateRange) (string, []interface{}) { 139 var args []interface{} 140 141 query := `select id, status, party_id, asset, amount, foreign_tx_hash, credited_timestamp, created_timestamp, tx_hash, vega_time 142 from deposits_current` 143 144 first := true 145 if party != "" { 146 query = fmt.Sprintf(`%s where party_id = %s`, query, nextBindVar(&args, entities.PartyID(party))) 147 first = false 148 } 149 150 return filterDateRange(query, depositsFilterDateColumn, dateRange, first, args...) 151 }