github.com/status-im/status-go@v1.1.0/services/wallet/blockchainstate/blockchainstate.go (about)

     1  package blockchainstate
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/status-im/status-go/services/wallet/common"
     9  )
    10  
    11  type LatestBlockData struct {
    12  	blockNumber   uint64
    13  	timestamp     time.Time
    14  	blockDuration time.Duration
    15  }
    16  
    17  type BlockChainState struct {
    18  	blkMu              sync.RWMutex
    19  	latestBlockNumbers map[uint64]LatestBlockData
    20  	sinceFn            func(time.Time) time.Duration
    21  }
    22  
    23  func NewBlockChainState() *BlockChainState {
    24  	return &BlockChainState{
    25  		blkMu:              sync.RWMutex{},
    26  		latestBlockNumbers: make(map[uint64]LatestBlockData),
    27  		sinceFn:            time.Since,
    28  	}
    29  }
    30  
    31  func (s *BlockChainState) GetEstimatedLatestBlockNumber(ctx context.Context, chainID uint64) (uint64, error) {
    32  	blockNumber, _ := s.estimateLatestBlockNumber(chainID)
    33  	return blockNumber, nil
    34  }
    35  
    36  func (s *BlockChainState) SetLastBlockNumber(chainID uint64, blockNumber uint64) {
    37  	blockDuration, found := common.AverageBlockDurationForChain[common.ChainID(chainID)]
    38  	if !found {
    39  		blockDuration = common.AverageBlockDurationForChain[common.ChainID(common.UnknownChainID)]
    40  	}
    41  	s.setLatestBlockDataForChain(chainID, LatestBlockData{
    42  		blockNumber:   blockNumber,
    43  		timestamp:     time.Now(),
    44  		blockDuration: blockDuration,
    45  	})
    46  }
    47  
    48  func (s *BlockChainState) setLatestBlockDataForChain(chainID uint64, latestBlockData LatestBlockData) {
    49  	s.blkMu.Lock()
    50  	defer s.blkMu.Unlock()
    51  	s.latestBlockNumbers[chainID] = latestBlockData
    52  }
    53  
    54  func (s *BlockChainState) estimateLatestBlockNumber(chainID uint64) (uint64, bool) {
    55  	s.blkMu.RLock()
    56  	defer s.blkMu.RUnlock()
    57  	blockData, ok := s.latestBlockNumbers[chainID]
    58  	if !ok {
    59  		return 0, false
    60  	}
    61  	timeDiff := s.sinceFn(blockData.timestamp)
    62  	return blockData.blockNumber + uint64((timeDiff / blockData.blockDuration)), true
    63  }