mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Add semaphore for API queries to SQL
This commit is contained in:
1026
db/historydb/apiqueries.go
Normal file
1026
db/historydb/apiqueries.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,6 @@
|
||||
package historydb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"strings"
|
||||
@@ -11,7 +9,6 @@ import (
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/db"
|
||||
"github.com/hermeznetwork/tracerr"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
//nolint:errcheck // driver for postgres DB
|
||||
@@ -30,12 +27,13 @@ const (
|
||||
|
||||
// HistoryDB persist the historic of the rollup
|
||||
type HistoryDB struct {
|
||||
db *sqlx.DB
|
||||
db *sqlx.DB
|
||||
apiConnCon *db.APIConnectionController
|
||||
}
|
||||
|
||||
// NewHistoryDB initialize the DB
|
||||
func NewHistoryDB(db *sqlx.DB) *HistoryDB {
|
||||
return &HistoryDB{db: db}
|
||||
func NewHistoryDB(db *sqlx.DB, apiConnCon *db.APIConnectionController) *HistoryDB {
|
||||
return &HistoryDB{db: db, apiConnCon: apiConnCon}
|
||||
}
|
||||
|
||||
// DB returns a pointer to the L2DB.db. This method should be used only for
|
||||
@@ -87,8 +85,8 @@ func (hdb *HistoryDB) GetAllBlocks() ([]common.Block, error) {
|
||||
return db.SlicePtrsToSlice(blocks).([]common.Block), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
|
||||
func (hdb *HistoryDB) GetBlocks(from, to int64) ([]common.Block, error) {
|
||||
// getBlocks retrieve blocks from the DB, given a range of block numbers defined by from and to
|
||||
func (hdb *HistoryDB) getBlocks(from, to int64) ([]common.Block, error) {
|
||||
var blocks []*common.Block
|
||||
err := meddler.QueryAll(
|
||||
hdb.db, &blocks,
|
||||
@@ -166,116 +164,6 @@ func (hdb *HistoryDB) addBatches(d meddler.DB, batches []common.Batch) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBatchAPI return the batch with the given batchNum
|
||||
func (hdb *HistoryDB) GetBatchAPI(batchNum common.BatchNum) (*BatchAPI, error) {
|
||||
batch := &BatchAPI{}
|
||||
return batch, tracerr.Wrap(meddler.QueryRow(
|
||||
hdb.db, batch,
|
||||
`SELECT batch.item_id, batch.batch_num, batch.eth_block_num,
|
||||
batch.forger_addr, batch.fees_collected, batch.total_fees_usd, batch.state_root,
|
||||
batch.num_accounts, batch.exit_root, batch.forge_l1_txs_num, batch.slot_num,
|
||||
block.timestamp, block.hash,
|
||||
COALESCE ((SELECT COUNT(*) FROM tx WHERE batch_num = batch.batch_num), 0) AS forged_txs
|
||||
FROM batch INNER JOIN block ON batch.eth_block_num = block.eth_block_num
|
||||
WHERE batch_num = $1;`, batchNum,
|
||||
))
|
||||
}
|
||||
|
||||
// GetBatchesAPI return the batches applying the given filters
|
||||
func (hdb *HistoryDB) GetBatchesAPI(
|
||||
minBatchNum, maxBatchNum, slotNum *uint,
|
||||
forgerAddr *ethCommon.Address,
|
||||
fromItem, limit *uint, order string,
|
||||
) ([]BatchAPI, uint64, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT batch.item_id, batch.batch_num, batch.eth_block_num,
|
||||
batch.forger_addr, batch.fees_collected, batch.total_fees_usd, batch.state_root,
|
||||
batch.num_accounts, batch.exit_root, batch.forge_l1_txs_num, batch.slot_num,
|
||||
block.timestamp, block.hash,
|
||||
COALESCE ((SELECT COUNT(*) FROM tx WHERE batch_num = batch.batch_num), 0) AS forged_txs,
|
||||
count(*) OVER() AS total_items
|
||||
FROM batch INNER JOIN block ON batch.eth_block_num = block.eth_block_num `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// minBatchNum filter
|
||||
if minBatchNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "batch.batch_num > ? "
|
||||
args = append(args, minBatchNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// maxBatchNum filter
|
||||
if maxBatchNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "batch.batch_num < ? "
|
||||
args = append(args, maxBatchNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// slotNum filter
|
||||
if slotNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "batch.slot_num = ? "
|
||||
args = append(args, slotNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// forgerAddr filter
|
||||
if forgerAddr != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "batch.forger_addr = ? "
|
||||
args = append(args, forgerAddr)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// pagination
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "batch.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "batch.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
queryStr += "ORDER BY batch.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
// log.Debug(query)
|
||||
batchPtrs := []*BatchAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &batchPtrs, query, args...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
batches := db.SlicePtrsToSlice(batchPtrs).([]BatchAPI)
|
||||
if len(batches) == 0 {
|
||||
return batches, 0, nil
|
||||
}
|
||||
return batches, batches[0].TotalItems - uint64(len(batches)), nil
|
||||
}
|
||||
|
||||
// GetAllBatches retrieve all batches from the DB
|
||||
func (hdb *HistoryDB) GetAllBatches() ([]common.Batch, error) {
|
||||
var batches []*common.Batch
|
||||
@@ -375,22 +263,6 @@ func (hdb *HistoryDB) GetAllBids() ([]common.Bid, error) {
|
||||
return db.SlicePtrsToSlice(bids).([]common.Bid), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetBestBidAPI returns the best bid in specific slot by slotNum
|
||||
func (hdb *HistoryDB) GetBestBidAPI(slotNum *int64) (BidAPI, error) {
|
||||
bid := &BidAPI{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, bid, `SELECT bid.*, block.timestamp, coordinator.forger_addr, coordinator.url
|
||||
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
||||
INNER JOIN (
|
||||
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||
GROUP BY bidder_addr
|
||||
) c ON bid.bidder_addr = c.bidder_addr
|
||||
INNER JOIN coordinator ON c.item_id = coordinator.item_id
|
||||
WHERE slot_num = $1 ORDER BY item_id DESC LIMIT 1;`, slotNum,
|
||||
)
|
||||
return *bid, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetBestBidCoordinator returns the forger address of the highest bidder in a slot by slotNum
|
||||
func (hdb *HistoryDB) GetBestBidCoordinator(slotNum int64) (*common.BidCoordinator, error) {
|
||||
bidCoord := &common.BidCoordinator{}
|
||||
@@ -416,133 +288,6 @@ func (hdb *HistoryDB) GetBestBidCoordinator(slotNum int64) (*common.BidCoordinat
|
||||
return bidCoord, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetBestBidsAPI returns the best bid in specific slot by slotNum
|
||||
func (hdb *HistoryDB) GetBestBidsAPI(
|
||||
minSlotNum, maxSlotNum *int64,
|
||||
bidderAddr *ethCommon.Address,
|
||||
limit *uint, order string,
|
||||
) ([]BidAPI, uint64, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
// JOIN the best bid of each slot with the latest update of each coordinator
|
||||
queryStr := `SELECT b.*, block.timestamp, coordinator.forger_addr, coordinator.url,
|
||||
COUNT(*) OVER() AS total_items FROM (
|
||||
SELECT slot_num, MAX(item_id) as maxitem
|
||||
FROM bid GROUP BY slot_num
|
||||
)
|
||||
AS x INNER JOIN bid AS b ON b.item_id = x.maxitem
|
||||
INNER JOIN block ON b.eth_block_num = block.eth_block_num
|
||||
INNER JOIN (
|
||||
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||
GROUP BY bidder_addr
|
||||
) c ON b.bidder_addr = c.bidder_addr
|
||||
INNER JOIN coordinator ON c.item_id = coordinator.item_id
|
||||
WHERE (b.slot_num >= ? AND b.slot_num <= ?)`
|
||||
args = append(args, minSlotNum)
|
||||
args = append(args, maxSlotNum)
|
||||
// Apply filters
|
||||
if bidderAddr != nil {
|
||||
queryStr += " AND b.bidder_addr = ? "
|
||||
args = append(args, bidderAddr)
|
||||
}
|
||||
queryStr += " ORDER BY b.slot_num "
|
||||
if order == OrderAsc {
|
||||
queryStr += "ASC "
|
||||
} else {
|
||||
queryStr += "DESC "
|
||||
}
|
||||
if limit != nil {
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
}
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
bidPtrs := []*BidAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &bidPtrs, query, args...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
// log.Debug(query)
|
||||
bids := db.SlicePtrsToSlice(bidPtrs).([]BidAPI)
|
||||
if len(bids) == 0 {
|
||||
return bids, 0, nil
|
||||
}
|
||||
return bids, bids[0].TotalItems - uint64(len(bids)), nil
|
||||
}
|
||||
|
||||
// GetBidsAPI return the bids applying the given filters
|
||||
func (hdb *HistoryDB) GetBidsAPI(
|
||||
slotNum *int64, bidderAddr *ethCommon.Address,
|
||||
fromItem, limit *uint, order string,
|
||||
) ([]BidAPI, uint64, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
// JOIN each bid with the latest update of each coordinator
|
||||
queryStr := `SELECT bid.*, block.timestamp, coord.forger_addr, coord.url,
|
||||
COUNT(*) OVER() AS total_items
|
||||
FROM bid INNER JOIN block ON bid.eth_block_num = block.eth_block_num
|
||||
INNER JOIN (
|
||||
SELECT bidder_addr, MAX(item_id) AS item_id FROM coordinator
|
||||
GROUP BY bidder_addr
|
||||
) c ON bid.bidder_addr = c.bidder_addr
|
||||
INNER JOIN coordinator coord ON c.item_id = coord.item_id `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// slotNum filter
|
||||
if slotNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "bid.slot_num = ? "
|
||||
args = append(args, slotNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// bidder filter
|
||||
if bidderAddr != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "bid.bidder_addr = ? "
|
||||
args = append(args, bidderAddr)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "bid.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "bid.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY bid.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += "ASC "
|
||||
} else {
|
||||
queryStr += "DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query, argsQ, err := sqlx.In(queryStr, args...)
|
||||
if err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
bids := []*BidAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &bids, query, argsQ...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
if len(bids) == 0 {
|
||||
return []BidAPI{}, 0, nil
|
||||
}
|
||||
return db.SlicePtrsToSlice(bids).([]BidAPI), bids[0].TotalItems - uint64(len(bids)), nil
|
||||
}
|
||||
|
||||
// AddCoordinators insert Coordinators into the DB
|
||||
func (hdb *HistoryDB) AddCoordinators(coordinators []common.Coordinator) error {
|
||||
return tracerr.Wrap(hdb.addCoordinators(hdb.db, coordinators))
|
||||
@@ -708,77 +453,6 @@ func (hdb *HistoryDB) GetAllTokens() ([]TokenWithUSD, error) {
|
||||
return db.SlicePtrsToSlice(tokens).([]TokenWithUSD), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetTokens returns a list of tokens from the DB
|
||||
func (hdb *HistoryDB) GetTokens(
|
||||
ids []common.TokenID, symbols []string, name string, fromItem,
|
||||
limit *uint, order string,
|
||||
) ([]TokenWithUSD, uint64, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT * , COUNT(*) OVER() AS total_items FROM token `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
if len(ids) > 0 {
|
||||
queryStr += "WHERE token_id IN (?) "
|
||||
nextIsAnd = true
|
||||
args = append(args, ids)
|
||||
}
|
||||
if len(symbols) > 0 {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "symbol IN (?) "
|
||||
args = append(args, symbols)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if name != "" {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "name ~ ? "
|
||||
args = append(args, name)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "item_id >= ? "
|
||||
} else {
|
||||
queryStr += "item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += "ASC "
|
||||
} else {
|
||||
queryStr += "DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query, argsQ, err := sqlx.In(queryStr, args...)
|
||||
if err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
tokens := []*TokenWithUSD{}
|
||||
if err := meddler.QueryAll(hdb.db, &tokens, query, argsQ...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
if len(tokens) == 0 {
|
||||
return []TokenWithUSD{}, 0, nil
|
||||
}
|
||||
return db.SlicePtrsToSlice(tokens).([]TokenWithUSD), uint64(len(tokens)) - tokens[0].TotalItems, nil
|
||||
}
|
||||
|
||||
// GetTokenSymbols returns all the token symbols from the DB
|
||||
func (hdb *HistoryDB) GetTokenSymbols() ([]string, error) {
|
||||
var tokenSymbols []string
|
||||
@@ -951,153 +625,6 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
|
||||
))
|
||||
}
|
||||
|
||||
// GetHistoryTx returns a tx from the DB given a TxID
|
||||
func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*TxAPI, error) {
|
||||
// Warning: amount_success and deposit_amount_success have true as default for
|
||||
// performance reasons. The expected default value is false (when txs are unforged)
|
||||
// this case is handled at the function func (tx TxAPI) MarshalJSON() ([]byte, error)
|
||||
tx := &TxAPI{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, tx, `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
||||
hez_idx(tx.effective_from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
||||
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
||||
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
||||
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
||||
tx.deposit_amount, tx.deposit_amount_usd, tx.deposit_amount_success, tx.fee, tx.fee_usd, tx.nonce,
|
||||
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr, token.name, token.symbol, token.decimals, token.usd,
|
||||
token.usd_update, block.timestamp
|
||||
FROM tx INNER JOIN token ON tx.token_id = token.token_id
|
||||
INNER JOIN block ON tx.eth_block_num = block.eth_block_num
|
||||
WHERE tx.id = $1;`, txID,
|
||||
)
|
||||
return tx, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetHistoryTxs returns a list of txs from the DB using the HistoryTx struct
|
||||
// and pagination info
|
||||
func (hdb *HistoryDB) GetHistoryTxs(
|
||||
ethAddr *ethCommon.Address, bjj *babyjub.PublicKeyComp,
|
||||
tokenID *common.TokenID, idx *common.Idx, batchNum *uint, txType *common.TxType,
|
||||
fromItem, limit *uint, order string,
|
||||
) ([]TxAPI, uint64, error) {
|
||||
// Warning: amount_success and deposit_amount_success have true as default for
|
||||
// performance reasons. The expected default value is false (when txs are unforged)
|
||||
// this case is handled at the function func (tx TxAPI) MarshalJSON() ([]byte, error)
|
||||
if ethAddr != nil && bjj != nil {
|
||||
return nil, 0, tracerr.Wrap(errors.New("ethAddr and bjj are incompatible"))
|
||||
}
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
|
||||
hez_idx(tx.effective_from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
|
||||
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
|
||||
tx.amount, tx.amount_success, tx.token_id, tx.amount_usd,
|
||||
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
|
||||
tx.deposit_amount, tx.deposit_amount_usd, tx.deposit_amount_success, tx.fee, tx.fee_usd, tx.nonce,
|
||||
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr, token.name, token.symbol, token.decimals, token.usd,
|
||||
token.usd_update, block.timestamp, count(*) OVER() AS total_items
|
||||
FROM tx INNER JOIN token ON tx.token_id = token.token_id
|
||||
INNER JOIN block ON tx.eth_block_num = block.eth_block_num `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// ethAddr filter
|
||||
if ethAddr != nil {
|
||||
queryStr += "WHERE (tx.from_eth_addr = ? OR tx.to_eth_addr = ?) "
|
||||
nextIsAnd = true
|
||||
args = append(args, ethAddr, ethAddr)
|
||||
} else if bjj != nil { // bjj filter
|
||||
queryStr += "WHERE (tx.from_bjj = ? OR tx.to_bjj = ?) "
|
||||
nextIsAnd = true
|
||||
args = append(args, bjj, bjj)
|
||||
}
|
||||
// tokenID filter
|
||||
if tokenID != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "tx.token_id = ? "
|
||||
args = append(args, tokenID)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// idx filter
|
||||
if idx != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "(tx.effective_from_idx = ? OR tx.to_idx = ?) "
|
||||
args = append(args, idx, idx)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// batchNum filter
|
||||
if batchNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "tx.batch_num = ? "
|
||||
args = append(args, batchNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// txType filter
|
||||
if txType != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "tx.type = ? "
|
||||
args = append(args, txType)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "tx.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "tx.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "tx.batch_num IS NOT NULL "
|
||||
|
||||
// pagination
|
||||
queryStr += "ORDER BY tx.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
// log.Debug(query)
|
||||
txsPtrs := []*TxAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &txsPtrs, query, args...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
txs := db.SlicePtrsToSlice(txsPtrs).([]TxAPI)
|
||||
if len(txs) == 0 {
|
||||
return txs, 0, nil
|
||||
}
|
||||
return txs, txs[0].TotalItems - uint64(len(txs)), nil
|
||||
}
|
||||
|
||||
// GetAllExits returns all exit from the DB
|
||||
func (hdb *HistoryDB) GetAllExits() ([]common.ExitInfo, error) {
|
||||
var exits []*common.ExitInfo
|
||||
@@ -1110,137 +637,6 @@ func (hdb *HistoryDB) GetAllExits() ([]common.ExitInfo, error) {
|
||||
return db.SlicePtrsToSlice(exits).([]common.ExitInfo), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetExitAPI returns a exit from the DB
|
||||
func (hdb *HistoryDB) GetExitAPI(batchNum *uint, idx *common.Idx) (*ExitAPI, error) {
|
||||
exit := &ExitAPI{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, exit, `SELECT exit_tree.item_id, exit_tree.batch_num,
|
||||
hez_idx(exit_tree.account_idx, token.symbol) AS account_idx,
|
||||
account.bjj, account.eth_addr,
|
||||
exit_tree.merkle_proof, exit_tree.balance, exit_tree.instant_withdrawn,
|
||||
exit_tree.delayed_withdraw_request, exit_tree.delayed_withdrawn,
|
||||
token.token_id, token.item_id AS token_item_id,
|
||||
token.eth_block_num AS token_block, token.eth_addr AS token_eth_addr, token.name, token.symbol,
|
||||
token.decimals, token.usd, token.usd_update
|
||||
FROM exit_tree INNER JOIN account ON exit_tree.account_idx = account.idx
|
||||
INNER JOIN token ON account.token_id = token.token_id
|
||||
WHERE exit_tree.batch_num = $1 AND exit_tree.account_idx = $2;`, batchNum, idx,
|
||||
)
|
||||
return exit, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetExitsAPI returns a list of exits from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetExitsAPI(
|
||||
ethAddr *ethCommon.Address, bjj *babyjub.PublicKeyComp, tokenID *common.TokenID,
|
||||
idx *common.Idx, batchNum *uint, onlyPendingWithdraws *bool,
|
||||
fromItem, limit *uint, order string,
|
||||
) ([]ExitAPI, uint64, error) {
|
||||
if ethAddr != nil && bjj != nil {
|
||||
return nil, 0, tracerr.Wrap(errors.New("ethAddr and bjj are incompatible"))
|
||||
}
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT exit_tree.item_id, exit_tree.batch_num,
|
||||
hez_idx(exit_tree.account_idx, token.symbol) AS account_idx,
|
||||
account.bjj, account.eth_addr,
|
||||
exit_tree.merkle_proof, exit_tree.balance, exit_tree.instant_withdrawn,
|
||||
exit_tree.delayed_withdraw_request, exit_tree.delayed_withdrawn,
|
||||
token.token_id, token.item_id AS token_item_id,
|
||||
token.eth_block_num AS token_block, token.eth_addr AS token_eth_addr, token.name, token.symbol,
|
||||
token.decimals, token.usd, token.usd_update, COUNT(*) OVER() AS total_items
|
||||
FROM exit_tree INNER JOIN account ON exit_tree.account_idx = account.idx
|
||||
INNER JOIN token ON account.token_id = token.token_id `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// ethAddr filter
|
||||
if ethAddr != nil {
|
||||
queryStr += "WHERE account.eth_addr = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, ethAddr)
|
||||
} else if bjj != nil { // bjj filter
|
||||
queryStr += "WHERE account.bjj = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, bjj)
|
||||
}
|
||||
// tokenID filter
|
||||
if tokenID != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "account.token_id = ? "
|
||||
args = append(args, tokenID)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// idx filter
|
||||
if idx != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "exit_tree.account_idx = ? "
|
||||
args = append(args, idx)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// batchNum filter
|
||||
if batchNum != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "exit_tree.batch_num = ? "
|
||||
args = append(args, batchNum)
|
||||
nextIsAnd = true
|
||||
}
|
||||
// onlyPendingWithdraws
|
||||
if onlyPendingWithdraws != nil {
|
||||
if *onlyPendingWithdraws {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "(exit_tree.instant_withdrawn IS NULL AND exit_tree.delayed_withdrawn IS NULL) "
|
||||
nextIsAnd = true
|
||||
}
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "exit_tree.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "exit_tree.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
// nextIsAnd = true
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY exit_tree.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
// log.Debug(query)
|
||||
exits := []*ExitAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &exits, query, args...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
if len(exits) == 0 {
|
||||
return []ExitAPI{}, 0, nil
|
||||
}
|
||||
return db.SlicePtrsToSlice(exits).([]ExitAPI), exits[0].TotalItems - uint64(len(exits)), nil
|
||||
}
|
||||
|
||||
// GetAllL1UserTxs returns all L1UserTxs from the DB
|
||||
func (hdb *HistoryDB) GetAllL1UserTxs() ([]common.L1Tx, error) {
|
||||
var txs []*common.L1Tx
|
||||
@@ -1381,19 +777,6 @@ func (hdb *HistoryDB) GetAllBucketUpdates() ([]common.BucketUpdate, error) {
|
||||
return db.SlicePtrsToSlice(bucketUpdates).([]common.BucketUpdate), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetBucketUpdates retrieves latest values for each bucket
|
||||
func (hdb *HistoryDB) GetBucketUpdates() ([]BucketUpdateAPI, error) {
|
||||
var bucketUpdates []*BucketUpdateAPI
|
||||
err := meddler.QueryAll(
|
||||
hdb.db, &bucketUpdates,
|
||||
`SELECT num_bucket, withdrawals FROM bucket_update
|
||||
WHERE item_id in(SELECT max(item_id) FROM bucket_update
|
||||
group by num_bucket)
|
||||
ORDER BY num_bucket ASC;`,
|
||||
)
|
||||
return db.SlicePtrsToSlice(bucketUpdates).([]BucketUpdateAPI), tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
func (hdb *HistoryDB) addTokenExchanges(d meddler.DB, tokenExchanges []common.TokenExchange) error {
|
||||
if len(tokenExchanges) == 0 {
|
||||
return nil
|
||||
@@ -1698,274 +1081,22 @@ func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*Coordina
|
||||
return coordinator, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetCoordinatorsAPI returns a list of coordinators from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetCoordinatorsAPI(
|
||||
bidderAddr, forgerAddr *ethCommon.Address,
|
||||
fromItem, limit *uint, order string,
|
||||
) ([]CoordinatorAPI, uint64, error) {
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT coordinator.*, COUNT(*) OVER() AS total_items
|
||||
FROM coordinator INNER JOIN (
|
||||
SELECT MAX(item_id) AS item_id FROM coordinator
|
||||
GROUP BY bidder_addr
|
||||
) c ON coordinator.item_id = c.item_id `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
if bidderAddr != nil {
|
||||
queryStr += "WHERE bidder_addr = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, bidderAddr)
|
||||
}
|
||||
if forgerAddr != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "forger_addr = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, forgerAddr)
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "coordinator.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "coordinator.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY coordinator.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query = hdb.db.Rebind(queryStr)
|
||||
|
||||
coordinators := []*CoordinatorAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &coordinators, query, args...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
if len(coordinators) == 0 {
|
||||
return []CoordinatorAPI{}, 0, nil
|
||||
}
|
||||
return db.SlicePtrsToSlice(coordinators).([]CoordinatorAPI),
|
||||
coordinators[0].TotalItems - uint64(len(coordinators)), nil
|
||||
}
|
||||
|
||||
// AddAuctionVars insert auction vars into the DB
|
||||
func (hdb *HistoryDB) AddAuctionVars(auctionVars *common.AuctionVariables) error {
|
||||
return tracerr.Wrap(meddler.Insert(hdb.db, "auction_vars", auctionVars))
|
||||
}
|
||||
|
||||
// GetAuctionVars returns auction variables
|
||||
func (hdb *HistoryDB) GetAuctionVars() (*common.AuctionVariables, error) {
|
||||
auctionVars := &common.AuctionVariables{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, auctionVars, `SELECT * FROM auction_vars;`,
|
||||
)
|
||||
return auctionVars, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
// GetAuctionVarsUntilSetSlotNum returns all the updates of the auction vars
|
||||
// from the last entry in which DefaultSlotSetBidSlotNum <= slotNum
|
||||
func (hdb *HistoryDB) GetAuctionVarsUntilSetSlotNum(slotNum int64, maxItems int) ([]MinBidInfo, error) {
|
||||
auctionVars := []*MinBidInfo{}
|
||||
query := `
|
||||
SELECT DISTINCT default_slot_set_bid, default_slot_set_bid_slot_num FROM auction_vars
|
||||
WHERE default_slot_set_bid_slot_num < $1
|
||||
ORDER BY default_slot_set_bid_slot_num DESC
|
||||
LIMIT $2;
|
||||
`
|
||||
err := meddler.QueryAll(hdb.db, &auctionVars, query, slotNum, maxItems)
|
||||
if err != nil {
|
||||
// GetTokensTest used to get tokens in a testing context
|
||||
func (hdb *HistoryDB) GetTokensTest() ([]TokenWithUSD, error) {
|
||||
tokens := []*TokenWithUSD{}
|
||||
if err := meddler.QueryAll(
|
||||
hdb.db, &tokens,
|
||||
"SELECT * FROM TOKEN",
|
||||
); err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
return db.SlicePtrsToSlice(auctionVars).([]MinBidInfo), nil
|
||||
}
|
||||
|
||||
// GetAccountAPI returns an account by its index
|
||||
func (hdb *HistoryDB) GetAccountAPI(idx common.Idx) (*AccountAPI, error) {
|
||||
account := &AccountAPI{}
|
||||
err := meddler.QueryRow(hdb.db, account, `SELECT account.item_id, hez_idx(account.idx,
|
||||
token.symbol) as idx, account.batch_num, account.bjj, account.eth_addr,
|
||||
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr as token_eth_addr, token.name, token.symbol, token.decimals, token.usd, token.usd_update
|
||||
FROM account INNER JOIN token ON account.token_id = token.token_id WHERE idx = $1;`, idx)
|
||||
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
||||
// GetAccountsAPI returns a list of accounts from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetAccountsAPI(
|
||||
tokenIDs []common.TokenID, ethAddr *ethCommon.Address,
|
||||
bjj *babyjub.PublicKeyComp, fromItem, limit *uint, order string,
|
||||
) ([]AccountAPI, uint64, error) {
|
||||
if ethAddr != nil && bjj != nil {
|
||||
return nil, 0, tracerr.Wrap(errors.New("ethAddr and bjj are incompatible"))
|
||||
}
|
||||
var query string
|
||||
var args []interface{}
|
||||
queryStr := `SELECT account.item_id, hez_idx(account.idx, token.symbol) as idx, account.batch_num,
|
||||
account.bjj, account.eth_addr, token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr as token_eth_addr, token.name, token.symbol, token.decimals, token.usd, token.usd_update,
|
||||
COUNT(*) OVER() AS total_items
|
||||
FROM account INNER JOIN token ON account.token_id = token.token_id `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// ethAddr filter
|
||||
if ethAddr != nil {
|
||||
queryStr += "WHERE account.eth_addr = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, ethAddr)
|
||||
} else if bjj != nil { // bjj filter
|
||||
queryStr += "WHERE account.bjj = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, bjj)
|
||||
}
|
||||
// tokenID filter
|
||||
if len(tokenIDs) > 0 {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "account.token_id IN (?) "
|
||||
args = append(args, tokenIDs)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "account.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "account.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY account.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query, argsQ, err := sqlx.In(queryStr, args...)
|
||||
if err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
|
||||
accounts := []*AccountAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &accounts, query, argsQ...); err != nil {
|
||||
return nil, 0, tracerr.Wrap(err)
|
||||
}
|
||||
if len(accounts) == 0 {
|
||||
return []AccountAPI{}, 0, nil
|
||||
}
|
||||
|
||||
return db.SlicePtrsToSlice(accounts).([]AccountAPI),
|
||||
accounts[0].TotalItems - uint64(len(accounts)), nil
|
||||
}
|
||||
|
||||
// GetMetrics returns metrics
|
||||
func (hdb *HistoryDB) GetMetrics(lastBatchNum common.BatchNum) (*Metrics, error) {
|
||||
metricsTotals := &MetricsTotals{}
|
||||
metrics := &Metrics{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, metricsTotals, `SELECT COUNT(tx.*) as total_txs,
|
||||
COALESCE (MIN(tx.batch_num), 0) as batch_num, COALESCE (MIN(block.timestamp),
|
||||
NOW()) AS min_timestamp, COALESCE (MAX(block.timestamp), NOW()) AS max_timestamp
|
||||
FROM tx INNER JOIN block ON tx.eth_block_num = block.eth_block_num
|
||||
WHERE block.timestamp >= NOW() - INTERVAL '24 HOURS';`)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
seconds := metricsTotals.MaxTimestamp.Sub(metricsTotals.MinTimestamp).Seconds()
|
||||
// Avoid dividing by 0
|
||||
if seconds == 0 {
|
||||
seconds++
|
||||
}
|
||||
|
||||
metrics.TransactionsPerSecond = float64(metricsTotals.TotalTransactions) / seconds
|
||||
|
||||
if (lastBatchNum - metricsTotals.FirstBatchNum) > 0 {
|
||||
metrics.TransactionsPerBatch = float64(metricsTotals.TotalTransactions) /
|
||||
float64(lastBatchNum-metricsTotals.FirstBatchNum+1)
|
||||
} else {
|
||||
metrics.TransactionsPerBatch = float64(0)
|
||||
}
|
||||
|
||||
err = meddler.QueryRow(
|
||||
hdb.db, metricsTotals, `SELECT COUNT(*) AS total_batches,
|
||||
COALESCE (SUM(total_fees_usd), 0) AS total_fees FROM batch
|
||||
WHERE batch_num > $1;`, metricsTotals.FirstBatchNum)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
if metricsTotals.TotalBatches > 0 {
|
||||
metrics.BatchFrequency = seconds / float64(metricsTotals.TotalBatches)
|
||||
} else {
|
||||
metrics.BatchFrequency = 0
|
||||
}
|
||||
if metricsTotals.TotalTransactions > 0 {
|
||||
metrics.AvgTransactionFee = metricsTotals.TotalFeesUSD / float64(metricsTotals.TotalTransactions)
|
||||
} else {
|
||||
metrics.AvgTransactionFee = 0
|
||||
}
|
||||
err = meddler.QueryRow(
|
||||
hdb.db, metrics,
|
||||
`SELECT COUNT(*) AS total_bjjs, COUNT(DISTINCT(bjj)) AS total_accounts FROM account;`)
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
return metrics, nil
|
||||
}
|
||||
|
||||
// GetAvgTxFee returns average transaction fee of the last 1h
|
||||
func (hdb *HistoryDB) GetAvgTxFee() (float64, error) {
|
||||
metricsTotals := &MetricsTotals{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, metricsTotals, `SELECT COUNT(tx.*) as total_txs,
|
||||
COALESCE (MIN(tx.batch_num), 0) as batch_num
|
||||
FROM tx INNER JOIN block ON tx.eth_block_num = block.eth_block_num
|
||||
WHERE block.timestamp >= NOW() - INTERVAL '1 HOURS';`)
|
||||
if err != nil {
|
||||
return 0, tracerr.Wrap(err)
|
||||
}
|
||||
err = meddler.QueryRow(
|
||||
hdb.db, metricsTotals, `SELECT COUNT(*) AS total_batches,
|
||||
COALESCE (SUM(total_fees_usd), 0) AS total_fees FROM batch
|
||||
WHERE batch_num > $1;`, metricsTotals.FirstBatchNum)
|
||||
if err != nil {
|
||||
return 0, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
var avgTransactionFee float64
|
||||
if metricsTotals.TotalTransactions > 0 {
|
||||
avgTransactionFee = metricsTotals.TotalFeesUSD / float64(metricsTotals.TotalTransactions)
|
||||
} else {
|
||||
avgTransactionFee = 0
|
||||
}
|
||||
|
||||
return avgTransactionFee, nil
|
||||
if len(tokens) == 0 {
|
||||
return []TokenWithUSD{}, nil
|
||||
}
|
||||
return db.SlicePtrsToSlice(tokens).([]TokenWithUSD), nil
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
var historyDB *HistoryDB
|
||||
var historyDBWithACC *HistoryDB
|
||||
|
||||
// In order to run the test you need to run a Posgres DB with
|
||||
// a database named "history" that is accessible by
|
||||
@@ -38,10 +39,12 @@ func TestMain(m *testing.M) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
historyDB = NewHistoryDB(db)
|
||||
historyDB = NewHistoryDB(db, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
apiConnCon := dbUtils.NewAPICnnectionController(1, time.Second)
|
||||
historyDBWithACC = NewHistoryDB(db, apiConnCon)
|
||||
// Run tests
|
||||
result := m.Run()
|
||||
// Close DB
|
||||
@@ -85,7 +88,7 @@ func TestBlocks(t *testing.T) {
|
||||
blocks...,
|
||||
)
|
||||
// Get all blocks from DB
|
||||
fetchedBlocks, err := historyDB.GetBlocks(fromBlock, toBlock)
|
||||
fetchedBlocks, err := historyDB.getBlocks(fromBlock, toBlock)
|
||||
assert.Equal(t, len(blocks), len(fetchedBlocks))
|
||||
// Compare generated vs getted blocks
|
||||
assert.NoError(t, err)
|
||||
@@ -245,9 +248,8 @@ func TestTokens(t *testing.T) {
|
||||
err := historyDB.AddTokens(tokens)
|
||||
assert.NoError(t, err)
|
||||
tokens = append([]common.Token{ethToken}, tokens...)
|
||||
limit := uint(10)
|
||||
// Fetch tokens
|
||||
fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
|
||||
fetchedTokens, err := historyDB.GetTokensTest()
|
||||
assert.NoError(t, err)
|
||||
// Compare fetched tokens vs generated tokens
|
||||
// All the tokens should have USDUpdate setted by the DB trigger
|
||||
@@ -267,7 +269,7 @@ func TestTokens(t *testing.T) {
|
||||
assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
|
||||
}
|
||||
// Fetch tokens
|
||||
fetchedTokens, _, err = historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
|
||||
fetchedTokens, err = historyDB.GetTokensTest()
|
||||
assert.NoError(t, err)
|
||||
// Compare fetched tokens vs generated tokens
|
||||
// All the tokens should have USDUpdate setted by the DB trigger
|
||||
@@ -302,9 +304,8 @@ func TestTokensUTF8(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
// Work with nonUTFTokens as tokens one gets updated and non UTF-8 characters are lost
|
||||
nonUTFTokens = append([]common.Token{ethToken}, nonUTFTokens...)
|
||||
limit := uint(10)
|
||||
// Fetch tokens
|
||||
fetchedTokens, _, err := historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
|
||||
fetchedTokens, err := historyDB.GetTokensTest()
|
||||
assert.NoError(t, err)
|
||||
// Compare fetched tokens vs generated tokens
|
||||
// All the tokens should have USDUpdate setted by the DB trigger
|
||||
@@ -324,7 +325,7 @@ func TestTokensUTF8(t *testing.T) {
|
||||
assert.NoError(t, historyDB.UpdateTokenValue(token.Symbol, value))
|
||||
}
|
||||
// Fetch tokens
|
||||
fetchedTokens, _, err = historyDB.GetTokens(nil, nil, "", nil, &limit, OrderAsc)
|
||||
fetchedTokens, err = historyDB.GetTokensTest()
|
||||
assert.NoError(t, err)
|
||||
// Compare fetched tokens vs generated tokens
|
||||
// All the tokens should have USDUpdate setted by the DB trigger
|
||||
@@ -1087,9 +1088,8 @@ func TestAddEscapeHatchWithdrawals(t *testing.T) {
|
||||
assert.Equal(t, escapeHatchWithdrawals, dbEscapeHatchWithdrawals)
|
||||
}
|
||||
|
||||
func TestGetMetrics(t *testing.T) {
|
||||
func TestGetMetricsAPI(t *testing.T) {
|
||||
test.WipeDB(historyDB.DB())
|
||||
|
||||
set := `
|
||||
Type: Blockchain
|
||||
|
||||
@@ -1146,7 +1146,7 @@ func TestGetMetrics(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
res, err := historyDB.GetMetrics(common.BatchNum(numBatches))
|
||||
res, err := historyDBWithACC.GetMetricsAPI(common.BatchNum(numBatches))
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, float64(numTx)/float64(numBatches-1), res.TransactionsPerBatch)
|
||||
@@ -1165,7 +1165,7 @@ func TestGetMetrics(t *testing.T) {
|
||||
assert.Equal(t, float64(0), res.AvgTransactionFee)
|
||||
}
|
||||
|
||||
func TestGetMetricsMoreThan24Hours(t *testing.T) {
|
||||
func TestGetMetricsAPIMoreThan24Hours(t *testing.T) {
|
||||
test.WipeDB(historyDB.DB())
|
||||
|
||||
testUsersLen := 3
|
||||
@@ -1226,7 +1226,7 @@ func TestGetMetricsMoreThan24Hours(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
res, err := historyDB.GetMetrics(common.BatchNum(numBatches))
|
||||
res, err := historyDBWithACC.GetMetricsAPI(common.BatchNum(numBatches))
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, math.Trunc((float64(numTx)/float64(numBatches-1))/0.001)*0.001, math.Trunc(res.TransactionsPerBatch/0.001)*0.001)
|
||||
@@ -1245,15 +1245,15 @@ func TestGetMetricsMoreThan24Hours(t *testing.T) {
|
||||
assert.Equal(t, float64(0), res.AvgTransactionFee)
|
||||
}
|
||||
|
||||
func TestGetMetricsEmpty(t *testing.T) {
|
||||
func TestGetMetricsAPIEmpty(t *testing.T) {
|
||||
test.WipeDB(historyDB.DB())
|
||||
_, err := historyDB.GetMetrics(0)
|
||||
_, err := historyDBWithACC.GetMetricsAPI(0)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGetAvgTxFeeEmpty(t *testing.T) {
|
||||
test.WipeDB(historyDB.DB())
|
||||
_, err := historyDB.GetAvgTxFee()
|
||||
_, err := historyDBWithACC.GetAvgTxFeeAPI()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user