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

     1  package transfer
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"sync"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/ethereum/go-ethereum/event"
    10  	"github.com/ethereum/go-ethereum/log"
    11  	"github.com/status-im/status-go/multiaccounts/accounts"
    12  	"github.com/status-im/status-go/rpc/chain"
    13  	"github.com/status-im/status-go/services/wallet/async"
    14  	"github.com/status-im/status-go/services/wallet/balance"
    15  	"github.com/status-im/status-go/services/wallet/blockchainstate"
    16  	"github.com/status-im/status-go/services/wallet/token"
    17  	"github.com/status-im/status-go/services/wallet/walletevent"
    18  	"github.com/status-im/status-go/transactions"
    19  )
    20  
    21  func NewSequentialFetchStrategy(db *Database, blockDAO *BlockDAO, blockRangesSeqDAO *BlockRangeSequentialDAO, accountsDB *accounts.Database, feed *event.Feed,
    22  	transactionManager *TransactionManager, pendingTxManager *transactions.PendingTxTracker,
    23  	tokenManager *token.Manager,
    24  	chainClients map[uint64]chain.ClientInterface,
    25  	accounts []common.Address,
    26  	balanceCacher balance.Cacher,
    27  	omitHistory bool,
    28  	blockChainState *blockchainstate.BlockChainState,
    29  ) *SequentialFetchStrategy {
    30  
    31  	return &SequentialFetchStrategy{
    32  		db:                 db,
    33  		blockDAO:           blockDAO,
    34  		blockRangesSeqDAO:  blockRangesSeqDAO,
    35  		accountsDB:         accountsDB,
    36  		feed:               feed,
    37  		transactionManager: transactionManager,
    38  		pendingTxManager:   pendingTxManager,
    39  		tokenManager:       tokenManager,
    40  		chainClients:       chainClients,
    41  		accounts:           accounts,
    42  		balanceCacher:      balanceCacher,
    43  		omitHistory:        omitHistory,
    44  		blockChainState:    blockChainState,
    45  	}
    46  }
    47  
    48  type SequentialFetchStrategy struct {
    49  	db                 *Database
    50  	blockDAO           *BlockDAO
    51  	blockRangesSeqDAO  *BlockRangeSequentialDAO
    52  	accountsDB         *accounts.Database
    53  	feed               *event.Feed
    54  	mu                 sync.Mutex
    55  	group              *async.Group
    56  	transactionManager *TransactionManager
    57  	pendingTxManager   *transactions.PendingTxTracker
    58  	tokenManager       *token.Manager
    59  	chainClients       map[uint64]chain.ClientInterface
    60  	accounts           []common.Address
    61  	balanceCacher      balance.Cacher
    62  	omitHistory        bool
    63  	blockChainState    *blockchainstate.BlockChainState
    64  }
    65  
    66  func (s *SequentialFetchStrategy) newCommand(chainClient chain.ClientInterface,
    67  	accounts []common.Address) async.Commander {
    68  
    69  	return newLoadBlocksAndTransfersCommand(accounts, s.db, s.accountsDB, s.blockDAO, s.blockRangesSeqDAO, chainClient, s.feed,
    70  		s.transactionManager, s.pendingTxManager, s.tokenManager, s.balanceCacher, s.omitHistory, s.blockChainState)
    71  }
    72  
    73  func (s *SequentialFetchStrategy) start() error {
    74  	s.mu.Lock()
    75  	defer s.mu.Unlock()
    76  
    77  	if s.group != nil {
    78  		return errAlreadyRunning
    79  	}
    80  	s.group = async.NewGroup(context.Background())
    81  
    82  	if s.feed != nil {
    83  		s.feed.Send(walletevent.Event{
    84  			Type:     EventFetchingRecentHistory,
    85  			Accounts: s.accounts,
    86  		})
    87  	}
    88  
    89  	for _, chainClient := range s.chainClients {
    90  		ctl := s.newCommand(chainClient, s.accounts)
    91  		s.group.Add(ctl.Command())
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  // Stop stops reactor loop and waits till it exits.
    98  func (s *SequentialFetchStrategy) stop() {
    99  	s.mu.Lock()
   100  	defer s.mu.Unlock()
   101  	if s.group == nil {
   102  		return
   103  	}
   104  	s.group.Stop()
   105  	s.group.Wait()
   106  	s.group = nil
   107  }
   108  
   109  func (s *SequentialFetchStrategy) kind() FetchStrategyType {
   110  	return SequentialFetchStrategyType
   111  }
   112  
   113  func (s *SequentialFetchStrategy) getTransfersByAddress(ctx context.Context, chainID uint64, address common.Address, toBlock *big.Int,
   114  	limit int64) ([]Transfer, error) {
   115  
   116  	log.Debug("[WalletAPI:: GetTransfersByAddress] get transfers for an address", "address", address,
   117  		"chainID", chainID, "toBlock", toBlock, "limit", limit)
   118  
   119  	rst, err := s.db.GetTransfersByAddress(chainID, address, toBlock, limit)
   120  	if err != nil {
   121  		log.Error("[WalletAPI:: GetTransfersByAddress] can't fetch transfers", "err", err)
   122  		return nil, err
   123  	}
   124  
   125  	return rst, nil
   126  }