Skip to content

Commit

Permalink
Merge pull request #73 from gateway-fm/fix/start_finish_retrieve-blocks
Browse files Browse the repository at this point in the history
Fix/start finish retrieve blocks
  • Loading branch information
Pashteto authored Aug 29, 2024
2 parents bf296b0 + 4c870aa commit 22d8a2f
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 175 deletions.
41 changes: 28 additions & 13 deletions perpsv3.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package perpsv3_Go

import (
"github.com/gateway-fm/perpsv3-Go/contracts/Account"
"math/big"

"github.com/gateway-fm/perpsv3-Go/contracts/Account"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

Expand Down Expand Up @@ -117,17 +118,20 @@ type IPerpsv3 interface {
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveMarketRegistered(limit uint64) ([]*models.MarketRegistered, error)

// RetrievePoolCreated is used to get all `PoolCreated` events from the Core contract with given block search
// RetrievePoolCreatedLimit is used to get all `PoolCreated` events from the Core contract with given block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrievePoolCreated(limit uint64) ([]*models.PoolCreated, error)
RetrievePoolCreatedLimit(limit uint64) ([]*models.PoolCreated, error)
RetrievePoolCreated(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.PoolCreated, error)

// RetrieveLiquidationsCore is used to get all `Liquidation` events from the Core contract with given block search
// RetrieveLiquidationsCoreLimit is used to get all `Liquidation` events from the Core contract with given block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveLiquidationsCore(limit uint64) ([]*models.CoreLiquidation, error)
RetrieveLiquidationsCoreLimit(limit uint64) ([]*models.CoreLiquidation, error)
RetrieveLiquidationsCore(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.CoreLiquidation, error)

// RetrieveVaultLiquidationsCore is used to get all `VaultLiquidation` events from the Core contract with given block search
// RetrieveVaultLiquidationsCoreLimit is used to get all `VaultLiquidation` events from the Core contract with given block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
RetrieveVaultLiquidationsCore(limit uint64) ([]*models.CoreVaultLiquidation, error)
RetrieveVaultLiquidationsCoreLimit(limit uint64) ([]*models.CoreVaultLiquidation, error)
RetrieveVaultLiquidationsCore(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.CoreVaultLiquidation, error)

// ListenTrades is used to subscribe on the contract "OrderSettled" event. The goroutine will return events on the
// TradesChan chanel and errors on the ErrChan chanel.
Expand Down Expand Up @@ -456,18 +460,29 @@ func (p *Perpsv3) RetrieveMarketRegistered(limit uint64) ([]*models.MarketRegist
return p.service.RetrieveMarketRegistered(limit)
}

func (p *Perpsv3) RetrievePoolCreated(limit uint64) ([]*models.PoolCreated, error) {
return p.service.RetrievePoolCreated(limit)
func (p *Perpsv3) RetrievePoolCreated(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.PoolCreated, error) {
return p.service.RetrievePoolCreated(fromBlock, toBlock, limit)
}

func (p *Perpsv3) RetrievePoolCreatedLimit(limit uint64) ([]*models.PoolCreated, error) {
return p.service.RetrievePoolCreatedLimit(limit)
}

func (p *Perpsv3) RetrieveLiquidationsCoreLimit(limit uint64) ([]*models.CoreLiquidation, error) {
return p.service.RetrieveLiquidationsCoreLimit(limit)
}

func (p *Perpsv3) RetrieveLiquidationsCore(limit uint64) ([]*models.CoreLiquidation, error) {
return p.service.RetrieveLiquidationsCore(limit)
func (p *Perpsv3) RetrieveVaultLiquidationsCoreLimit(limit uint64) ([]*models.CoreVaultLiquidation, error) {
return p.service.RetrieveVaultLiquidationsCoreLimit(limit)
}

func (p *Perpsv3) RetrieveVaultLiquidationsCore(limit uint64) ([]*models.CoreVaultLiquidation, error) {
return p.service.RetrieveVaultLiquidationsCore(limit)
func (p *Perpsv3) RetrieveLiquidationsCore(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.CoreLiquidation, error) {
return p.service.RetrieveLiquidationsCore(fromBlock, toBlock, limit)
}

func (p *Perpsv3) RetrieveVaultLiquidationsCore(fromBlock uint64, toBlock uint64, limit uint64) ([]*models.CoreVaultLiquidation, error) {
return p.service.RetrieveVaultLiquidationsCore(fromBlock, toBlock, limit)
}
func (p *Perpsv3) ListenTrades() (*events.TradeSubscription, error) {
return p.events.ListenTrades()
}
Expand Down
157 changes: 86 additions & 71 deletions services/liquidationsCore.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package services

import (
"context"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
Expand All @@ -12,64 +13,69 @@ import (
"github.com/gateway-fm/perpsv3-Go/pkg/logger"
)

func (s *Service) RetrieveLiquidationsCore(limit uint64) ([]*models.CoreLiquidation, error) {
iterations, last, err := s.getIterationsForLimitQueryCore(limit)
func (s *Service) RetrieveLiquidationsCoreLimit(limit uint64) ([]*models.CoreLiquidation, error) {
return s.RetrieveLiquidationsCore(0, 0, limit)
}

func (s *Service) retrieveLiquidationsCore(opts *bind.FilterOpts) ([]*models.CoreLiquidation, error) {
iterator, err := s.core.FilterLiquidation(opts, nil, nil, nil)
if err != nil {
return nil, err
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf("error get iterator: %v", err.Error())
return nil, errors.GetFilterErr(err, "core")
}

var liquidations []*models.CoreLiquidation

logger.Log().WithField("layer", "Service-RetrieveLiquidationsCoreLimit").Infof(
"fetching liquidations with limit: %v to block: %v total iterations: %v...",
limit, last, iterations,
)

fromBlock := s.coreFirstBlock
toBlock := fromBlock + limit
for i := uint64(1); i <= iterations; i++ {
if i%10 == 0 || i == iterations {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCoreLimit").Infof("-- iteration %v", i)
for iterator.Next() {
if iterator.Error() != nil {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf("iterator error: %v", iterator.Error().Error())
return nil, errors.GetFilterErr(iterator.Error(), "core")
}
opts := s.getFilterOptsCore(fromBlock, &toBlock)

res, err := s.retrieveLiquidationsCore(opts)
liquidation, err := s.getLiquidationCore(iterator.Event, iterator.Event.Raw.BlockNumber)
if err != nil {
return nil, err
}

liquidations = append(liquidations, res...)
liquidations = append(liquidations, liquidation)
}

fromBlock = toBlock + 1
return liquidations, nil
}

if i == iterations-1 {
toBlock = last
} else {
toBlock = fromBlock + limit
}
// getLiquidationCore is used to get models.CoreLiquidation from given event and block number
func (s *Service) getLiquidationCore(event *core.CoreLiquidation, blockN uint64) (*models.CoreLiquidation, error) {
block, err := s.rpcClient.HeaderByNumber(context.Background(), big.NewInt(int64(blockN)))
if err != nil {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf(
"get block:%v by number error: %v", blockN, err.Error(),
)
return nil, errors.GetRPCProviderErr(err, "HeaderByNumber")
}

logger.Log().WithField("layer", "Service-RetrieveLiquidationsCoreLimit").Infof("task completed successfully")
return models.GetCoreLiquidationFromEvent(event, block.Time), nil
}

return liquidations, nil
func (s *Service) RetrieveVaultLiquidationsCoreLimit(limit uint64) ([]*models.CoreVaultLiquidation, error) {
return s.RetrieveVaultLiquidationsCore(0, 0, limit)
}

func (s *Service) retrieveLiquidationsCore(opts *bind.FilterOpts) ([]*models.CoreLiquidation, error) {
iterator, err := s.core.FilterLiquidation(opts, nil, nil, nil)
func (s *Service) retrieveVaultLiquidationsCore(opts *bind.FilterOpts) ([]*models.CoreVaultLiquidation, error) {
iterator, err := s.core.FilterVaultLiquidation(opts, nil, nil)
if err != nil {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf("error get iterator: %v", err.Error())
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf("error get iterator: %v", err.Error())
return nil, errors.GetFilterErr(err, "core")
}

var liquidations []*models.CoreLiquidation
var liquidations []*models.CoreVaultLiquidation

for iterator.Next() {
if iterator.Error() != nil {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf("iterator error: %v", iterator.Error().Error())
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf("iterator error: %v", iterator.Error().Error())
return nil, errors.GetFilterErr(iterator.Error(), "core")
}

liquidation, err := s.getLiquidationCore(iterator.Event, iterator.Event.Raw.BlockNumber)
liquidation, err := s.getVaultLiquidationCore(iterator.Event, iterator.Event.Raw.BlockNumber)
if err != nil {
return nil, err
}
Expand All @@ -80,96 +86,105 @@ func (s *Service) retrieveLiquidationsCore(opts *bind.FilterOpts) ([]*models.Cor
return liquidations, nil
}

// getLiquidationCore is used to get models.CoreLiquidation from given event and block number
func (s *Service) getLiquidationCore(event *core.CoreLiquidation, blockN uint64) (*models.CoreLiquidation, error) {
// getVaultLiquidationCore is used to get models.CoreVaultLiquidation from given event and block number
func (s *Service) getVaultLiquidationCore(event *core.CoreVaultLiquidation, blockN uint64) (*models.CoreVaultLiquidation, error) {
block, err := s.rpcClient.HeaderByNumber(context.Background(), big.NewInt(int64(blockN)))
if err != nil {
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Errorf(
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf(
"get block:%v by number error: %v", blockN, err.Error(),
)
return nil, errors.GetRPCProviderErr(err, "HeaderByNumber")
}

return models.GetCoreLiquidationFromEvent(event, block.Time), nil
return models.GetCoreVaultLiquidationFromEvent(event, block.Time), nil
}

func (s *Service) RetrieveVaultLiquidationsCore(limit uint64) ([]*models.CoreVaultLiquidation, error) {
iterations, last, err := s.getIterationsForLimitQueryCore(limit)
func (s *Service) RetrieveLiquidationsCore(fromBlock uint64, toBlock1 uint64, limit uint64) ([]*models.CoreLiquidation, error) {
iterations, lastBlock, err := s.getIterationsForQuery(fromBlock, toBlock1, limit, ContractCore)
if err != nil {
return nil, err
return nil, fmt.Errorf("cant getIterationsForQuery: %w", err)
}
if fromBlock == 0 {
fromBlock = s.coreFirstBlock
}

var liquidations []*models.CoreVaultLiquidation
var liquidations []*models.CoreLiquidation

logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCoreLimit").Infof(
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Infof(
"fetching liquidations with limit: %v to block: %v total iterations: %v...",
limit, last, iterations,
limit, lastBlock, iterations,
)

fromBlock := s.coreFirstBlock
toBlock := fromBlock + limit
toBlock2 := fromBlock + limit
for i := uint64(1); i <= iterations; i++ {
if i%10 == 0 || i == iterations {
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCoreLimit").Infof("-- iteration %v", i)
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Infof("-- iteration %v", i)
}
opts := s.getFilterOptsCore(fromBlock, &toBlock)
opts := s.getFilterOptsCore(fromBlock, &toBlock2)

res, err := s.retrieveVaultLiquidationsCore(opts)
res, err := s.retrieveLiquidationsCore(opts)
if err != nil {
return nil, err
}

liquidations = append(liquidations, res...)

fromBlock = toBlock + 1
fromBlock = toBlock2 + 1

if i == iterations-1 {
toBlock = last
toBlock2 = lastBlock
} else {
toBlock = fromBlock + limit
toBlock2 = fromBlock + limit
}
}

logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCoreLimit").Infof("task completed successfully")
logger.Log().WithField("layer", "Service-RetrieveLiquidationsCore").Infof("task completed successfully")

return liquidations, nil
}

func (s *Service) retrieveVaultLiquidationsCore(opts *bind.FilterOpts) ([]*models.CoreVaultLiquidation, error) {
iterator, err := s.core.FilterVaultLiquidation(opts, nil, nil)
// RetrieveVaultLiquidationsCore is used to get all `DelegationUpdated` events with given start block, end block and block search
// limit. For most public RPC providers the value for limit is 20 000 blocks
func (s *Service) RetrieveVaultLiquidationsCore(fromBlock uint64, toBlock1 uint64, limit uint64) ([]*models.CoreVaultLiquidation, error) {
iterations, lastBlock, err := s.getIterationsForQuery(fromBlock, toBlock1, limit, ContractCore)
if err != nil {
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf("error get iterator: %v", err.Error())
return nil, errors.GetFilterErr(err, "core")
return nil, fmt.Errorf("cant getIterationsForQuery: %w", err)
}
if fromBlock == 0 {
fromBlock = s.coreFirstBlock
}

var liquidations []*models.CoreVaultLiquidation

for iterator.Next() {
if iterator.Error() != nil {
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf("iterator error: %v", iterator.Error().Error())
return nil, errors.GetFilterErr(iterator.Error(), "core")
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Infof(
"fetching liquidations with limit: %v to block: %v total iterations: %v...",
limit, lastBlock, iterations,
)

toBlock2 := fromBlock + limit
for i := uint64(1); i <= iterations; i++ {
if i%10 == 0 || i == iterations {
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Infof("-- iteration %v", i)
}
opts := s.getFilterOptsCore(fromBlock, &toBlock2)

liquidation, err := s.getVaultLiquidationCore(iterator.Event, iterator.Event.Raw.BlockNumber)
res, err := s.retrieveVaultLiquidationsCore(opts)
if err != nil {
return nil, err
}

liquidations = append(liquidations, liquidation)
}
liquidations = append(liquidations, res...)

return liquidations, nil
}
fromBlock = toBlock2 + 1

// getVaultLiquidationCore is used to get models.CoreVaultLiquidation from given event and block number
func (s *Service) getVaultLiquidationCore(event *core.CoreVaultLiquidation, blockN uint64) (*models.CoreVaultLiquidation, error) {
block, err := s.rpcClient.HeaderByNumber(context.Background(), big.NewInt(int64(blockN)))
if err != nil {
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Errorf(
"get block:%v by number error: %v", blockN, err.Error(),
)
return nil, errors.GetRPCProviderErr(err, "HeaderByNumber")
if i == iterations-1 {
toBlock2 = lastBlock
} else {
toBlock2 = fromBlock + limit
}
}

return models.GetCoreVaultLiquidationFromEvent(event, block.Time), nil
logger.Log().WithField("layer", "Service-RetrieveVaultLiquidationsCore").Infof("task completed successfully")

return liquidations, nil
}
Loading

0 comments on commit 22d8a2f

Please sign in to comment.