package database
import (
"fmt"
"time"
"github.com/forbole/callisto/v4/types"
dbtypes "github.com/forbole/callisto/v4/database/types"
)
func (db *CyberDb) GetLastBlock() (*dbtypes.BlockRow, error) {
stmt := `SELECT * FROM block ORDER BY height DESC LIMIT 1`
var blocks []dbtypes.BlockRow
if err := db.Sqlx.Select(&blocks, stmt); err != nil {
return nil, err
}
if len(blocks) == 0 {
return nil, fmt.Errorf("cannot get block, no blocks saved")
}
return &blocks[0], nil
}
func (db *CyberDb) GetLastBlockHeightAndTimestamp() (dbtypes.BlockHeightAndTimestamp, error) {
stmt := `SELECT height, timestamp FROM block ORDER BY height DESC LIMIT 1`
var blockHeightAndTimestamp []dbtypes.BlockHeightAndTimestamp
if err := db.Sqlx.Select(&blockHeightAndTimestamp, stmt); err != nil {
return dbtypes.BlockHeightAndTimestamp{}, fmt.Errorf("cannot get last block height and timestamp from db: %s", err)
}
if len(blockHeightAndTimestamp) == 0 {
return dbtypes.BlockHeightAndTimestamp{}, nil
}
return blockHeightAndTimestamp[0], nil
}
func (db *CyberDb) getBlockHeightTime(pastTime time.Time) (dbtypes.BlockRow, error) {
stmt := `SELECT * FROM block WHERE block.timestamp <= $1 ORDER BY block.timestamp DESC LIMIT 1;`
var val []dbtypes.BlockRow
if err := db.Sqlx.Select(&val, stmt, pastTime); err != nil {
return dbtypes.BlockRow{}, err
}
if len(val) == 0 {
return dbtypes.BlockRow{}, fmt.Errorf("cannot get block time, no blocks saved")
}
return val[0], nil
}
func (db *CyberDb) GetBlockHeightTimeMinuteAgo(now time.Time) (dbtypes.BlockRow, error) {
pastTime := now.Add(time.Minute * -1)
return db.getBlockHeightTime(pastTime)
}
func (db *CyberDb) GetBlockHeightTimeHourAgo(now time.Time) (dbtypes.BlockRow, error) {
pastTime := now.Add(time.Hour * -1)
return db.getBlockHeightTime(pastTime)
}
func (db *CyberDb) GetBlockHeightTimeDayAgo(now time.Time) (dbtypes.BlockRow, error) {
pastTime := now.Add(time.Hour * -24)
return db.getBlockHeightTime(pastTime)
}
func (db *CyberDb) SaveAverageBlockTimePerMin(averageTime float64, height int64) error {
stmt := `
INSERT INTO average_block_time_per_minute(average_time, height)
VALUES ($1, $)
ON CONFLICT (one_row_id) DO UPDATE
SET average_time = excluded.average_time,
height = excluded.height
WHERE average_block_time_per_minute.height <= excluded.height`
_, err := db.Sqlx.Exec(stmt, averageTime, height)
if err != nil {
return fmt.Errorf("error while storing average block time per minute: %s", err)
}
return nil
}
func (db *CyberDb) SaveAverageBlockTimePerHour(averageTime float64, height int64) error {
stmt := `
INSERT INTO average_block_time_per_hour(average_time, height)
VALUES (MATH_PLACEHOLDER_12)
ON CONFLICT (one_row_id) DO UPDATE
SET average_time = excluded.average_time,
height = excluded.height
WHERE average_block_time_per_hour.height <= excluded.height`
_, err := db.Sqlx.Exec(stmt, averageTime, height)
if err != nil {
return fmt.Errorf("error while storing average block time per hour: %s", err)
}
return nil
}
func (db *CyberDb) SaveAverageBlockTimePerDay(averageTime float64, height int64) error {
stmt := `
INSERT INTO average_block_time_per_day(average_time, height)
VALUES (MATH_PLACEHOLDER_22)
ON CONFLICT (one_row_id) DO UPDATE
SET average_time = excluded.average_time,
height = excluded.height
WHERE average_block_time_per_day.height <= excluded.height`
_, err := db.Sqlx.Exec(stmt, averageTime, height)
if err != nil {
return fmt.Errorf("error while storing average block time per day: %s", err)
}
return nil
}
func (db *CyberDb) SaveAverageBlockTimeGenesis(averageTime float64, height int64) error {
stmt := `
INSERT INTO average_block_time_from_genesis(average_time ,height)
VALUES (MATH_PLACEHOLDER_32)
ON CONFLICT (one_row_id) DO UPDATE
SET average_time = excluded.average_time,
height = excluded.height
WHERE average_block_time_from_genesis.height <= excluded.height`
_, err := db.Sqlx.Exec(stmt, averageTime, height)
if err != nil {
return fmt.Errorf("error while storing average block time since genesis: %s", err)
}
return nil
}
func (db *CyberDb) SaveGenesis(genesis *types.Genesis) error {
stmt := `
INSERT INTO genesis(time, chain_id, initial_height)
VALUES (MATH_PLACEHOLDER_42, $3) ON CONFLICT (one_row_id) DO UPDATE
SET time = excluded.time,
initial_height = excluded.initial_height,
chain_id = excluded.chain_id`
_, err := db.Sqlx.Exec(stmt, genesis.Time, genesis.ChainID, genesis.InitialHeight)
if err != nil {
return fmt.Errorf("error while storing genesis: %s", err)
}
return nil
}
func (db *CyberDb) GetGenesis() (*types.Genesis, error) {
var rows []*dbtypes.GenesisRow
err := db.Sqlx.Select(&rows, `SELECT * FROM genesis;`)
if err != nil {
return nil, err
}
if len(rows) == 0 {
return nil, fmt.Errorf("no rows inside the genesis table")
}
row := rows[0]
return types.NewGenesis(row.ChainID, row.Time, row.InitialHeight), nil
}