147 lines
4.1 KiB
Go
147 lines
4.1 KiB
Go
package transfer
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/log"
|
|
"github.com/status-im/status-go/services/wallet/bigint"
|
|
)
|
|
|
|
const (
|
|
firstBlockColumn = "blk_first"
|
|
lastBlockColumn = "blk_last"
|
|
startBlockColumn = "blk_start"
|
|
)
|
|
|
|
type BlockRangeSequentialDAO struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
type BlockRange struct {
|
|
Start *big.Int // Block of first transfer
|
|
FirstKnown *big.Int // Oldest scanned block
|
|
LastKnown *big.Int // Last scanned block
|
|
}
|
|
|
|
func NewBlockRange() *BlockRange {
|
|
return &BlockRange{Start: &big.Int{}, FirstKnown: &big.Int{}, LastKnown: &big.Int{}}
|
|
}
|
|
|
|
func (b *BlockRangeSequentialDAO) getBlockRange(chainID uint64, address common.Address) (blockRange *BlockRange, err error) {
|
|
query := `SELECT blk_start, blk_first, blk_last FROM blocks_ranges_sequential
|
|
WHERE address = ?
|
|
AND network_id = ?`
|
|
|
|
rows, err := b.db.Query(query, address, chainID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
if rows.Next() {
|
|
blockRange = NewBlockRange()
|
|
err = rows.Scan((*bigint.SQLBigInt)(blockRange.Start), (*bigint.SQLBigInt)(blockRange.FirstKnown), (*bigint.SQLBigInt)(blockRange.LastKnown))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return blockRange, nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
// TODO call it when account is removed
|
|
//
|
|
//lint:ignore U1000 Ignore unused function temporarily
|
|
func (b *BlockRangeSequentialDAO) deleteRange(chainID uint64, account common.Address) error {
|
|
log.Info("delete blocks range", "account", account, "network", chainID)
|
|
delete, err := b.db.Prepare(`DELETE FROM blocks_ranges_sequential
|
|
WHERE address = ?
|
|
AND network_id = ?`)
|
|
if err != nil {
|
|
log.Info("some error", "error", err)
|
|
return err
|
|
}
|
|
|
|
_, err = delete.Exec(account, chainID)
|
|
return err
|
|
}
|
|
|
|
func (b *BlockRangeSequentialDAO) updateStartBlock(chainID uint64, account common.Address, block *big.Int) (err error) {
|
|
return updateBlock(b.db, chainID, account, startBlockColumn, block)
|
|
}
|
|
|
|
//lint:ignore U1000 Ignore unused function temporarily, TODO use it when new transfers are fetched
|
|
func (b *BlockRangeSequentialDAO) updateLastBlock(chainID uint64, account common.Address, block *big.Int) (err error) {
|
|
return updateBlock(b.db, chainID, account, lastBlockColumn, block)
|
|
}
|
|
|
|
func (b *BlockRangeSequentialDAO) updateFirstBlock(chainID uint64, account common.Address, block *big.Int) (err error) {
|
|
return updateBlock(b.db, chainID, account, firstBlockColumn, block)
|
|
}
|
|
|
|
func updateBlock(creator statementCreator, chainID uint64, account common.Address,
|
|
blockColumn string, block *big.Int) (err error) {
|
|
|
|
update, err := creator.Prepare(fmt.Sprintf(`UPDATE blocks_ranges_sequential
|
|
SET %s = ?
|
|
WHERE address = ?
|
|
AND network_id = ?`, blockColumn))
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = update.Exec((*bigint.SQLBigInt)(block), account, chainID)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (b *BlockRangeSequentialDAO) upsertRange(chainID uint64, account common.Address,
|
|
start *big.Int, first *big.Int, last *big.Int) (err error) {
|
|
|
|
log.Info("upsert blocks range", "account", account, "network id", chainID, "start", start, "first", first, "last", last)
|
|
|
|
update, err := b.db.Prepare(`UPDATE blocks_ranges_sequential
|
|
SET blk_start = ?,
|
|
blk_first = ?,
|
|
blk_last = ?
|
|
WHERE address = ?
|
|
AND network_id = ?`)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
res, err := update.Exec((*bigint.SQLBigInt)(start), (*bigint.SQLBigInt)(first), (*bigint.SQLBigInt)(last), account, chainID)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
affected, err := res.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected == 0 {
|
|
insert, err := b.db.Prepare("INSERT INTO blocks_ranges_sequential (network_id, address, blk_first, blk_last, blk_start) VALUES (?, ?, ?, ?, ?)")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = insert.Exec(chainID, account, (*bigint.SQLBigInt)(first), (*bigint.SQLBigInt)(last), (*bigint.SQLBigInt)(start))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|