status-go/services/wallet/blockchainstate/blockchainstate.go

64 lines
1.7 KiB
Go

package blockchainstate
import (
"context"
"sync"
"time"
"github.com/status-im/status-go/services/wallet/common"
)
type LatestBlockData struct {
blockNumber uint64
timestamp time.Time
blockDuration time.Duration
}
type BlockChainState struct {
blkMu sync.RWMutex
latestBlockNumbers map[uint64]LatestBlockData
sinceFn func(time.Time) time.Duration
}
func NewBlockChainState() *BlockChainState {
return &BlockChainState{
blkMu: sync.RWMutex{},
latestBlockNumbers: make(map[uint64]LatestBlockData),
sinceFn: time.Since,
}
}
func (s *BlockChainState) GetEstimatedLatestBlockNumber(ctx context.Context, chainID uint64) (uint64, error) {
blockNumber, _ := s.estimateLatestBlockNumber(chainID)
return blockNumber, nil
}
func (s *BlockChainState) SetLastBlockNumber(chainID uint64, blockNumber uint64) {
blockDuration, found := common.AverageBlockDurationForChain[common.ChainID(chainID)]
if !found {
blockDuration = common.AverageBlockDurationForChain[common.ChainID(common.UnknownChainID)]
}
s.setLatestBlockDataForChain(chainID, LatestBlockData{
blockNumber: blockNumber,
timestamp: time.Now(),
blockDuration: blockDuration,
})
}
func (s *BlockChainState) setLatestBlockDataForChain(chainID uint64, latestBlockData LatestBlockData) {
s.blkMu.Lock()
defer s.blkMu.Unlock()
s.latestBlockNumbers[chainID] = latestBlockData
}
func (s *BlockChainState) estimateLatestBlockNumber(chainID uint64) (uint64, bool) {
s.blkMu.RLock()
defer s.blkMu.RUnlock()
blockData, ok := s.latestBlockNumbers[chainID]
if !ok {
return 0, false
}
timeDiff := s.sinceFn(blockData.timestamp)
return blockData.blockNumber + uint64((timeDiff / blockData.blockDuration)), true
}