github.com/status-im/status-go@v1.1.0/services/wallet/transfer/reactor.go (about) 1 package transfer 2 3 import ( 4 "context" 5 "errors" 6 "math/big" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/core/types" 10 "github.com/ethereum/go-ethereum/event" 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/balance" 14 "github.com/status-im/status-go/services/wallet/blockchainstate" 15 "github.com/status-im/status-go/services/wallet/token" 16 "github.com/status-im/status-go/transactions" 17 ) 18 19 const ( 20 ReactorNotStarted string = "reactor not started" 21 22 NonArchivalNodeBlockChunkSize = 100 23 DefaultNodeBlockChunkSize = 100000 24 ) 25 26 var errAlreadyRunning = errors.New("already running") 27 28 type FetchStrategyType int32 29 30 const ( 31 SequentialFetchStrategyType FetchStrategyType = iota 32 ) 33 34 // HeaderReader interface for reading headers using block number or hash. 35 type HeaderReader interface { 36 HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) 37 HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) 38 } 39 40 type HistoryFetcher interface { 41 start() error 42 stop() 43 kind() FetchStrategyType 44 45 getTransfersByAddress(ctx context.Context, chainID uint64, address common.Address, toBlock *big.Int, 46 limit int64) ([]Transfer, error) 47 } 48 49 // Reactor listens to new blocks and stores transfers into the database. 50 type Reactor struct { 51 db *Database 52 blockDAO *BlockDAO 53 blockRangesSeqDAO *BlockRangeSequentialDAO 54 accountsDB *accounts.Database 55 feed *event.Feed 56 transactionManager *TransactionManager 57 pendingTxManager *transactions.PendingTxTracker 58 tokenManager *token.Manager 59 strategy HistoryFetcher 60 balanceCacher balance.Cacher 61 omitHistory bool 62 blockChainState *blockchainstate.BlockChainState 63 chainIDs []uint64 64 } 65 66 func NewReactor(db *Database, blockDAO *BlockDAO, blockRangesSeqDAO *BlockRangeSequentialDAO, accountsDB *accounts.Database, feed *event.Feed, tm *TransactionManager, 67 pendingTxManager *transactions.PendingTxTracker, tokenManager *token.Manager, 68 balanceCacher balance.Cacher, omitHistory bool, blockChainState *blockchainstate.BlockChainState) *Reactor { 69 return &Reactor{ 70 db: db, 71 accountsDB: accountsDB, 72 blockDAO: blockDAO, 73 blockRangesSeqDAO: blockRangesSeqDAO, 74 feed: feed, 75 transactionManager: tm, 76 pendingTxManager: pendingTxManager, 77 tokenManager: tokenManager, 78 balanceCacher: balanceCacher, 79 omitHistory: omitHistory, 80 blockChainState: blockChainState, 81 } 82 } 83 84 // Start runs reactor loop in background. 85 func (r *Reactor) start(chainClients map[uint64]chain.ClientInterface, accounts []common.Address) error { 86 chainIDs := []uint64{} 87 for _, client := range chainClients { 88 chainIDs = append(chainIDs, client.NetworkID()) 89 } 90 r.chainIDs = chainIDs 91 r.strategy = r.createFetchStrategy(chainClients, accounts) 92 return r.strategy.start() 93 } 94 95 // Stop stops reactor loop and waits till it exits. 96 func (r *Reactor) stop() { 97 if r.strategy != nil { 98 r.strategy.stop() 99 } 100 } 101 102 func (r *Reactor) restart(chainClients map[uint64]chain.ClientInterface, accounts []common.Address) error { 103 104 r.stop() 105 return r.start(chainClients, accounts) 106 } 107 108 func (r *Reactor) createFetchStrategy(chainClients map[uint64]chain.ClientInterface, 109 accounts []common.Address) HistoryFetcher { 110 111 return NewSequentialFetchStrategy( 112 r.db, 113 r.blockDAO, 114 r.blockRangesSeqDAO, 115 r.accountsDB, 116 r.feed, 117 r.transactionManager, 118 r.pendingTxManager, 119 r.tokenManager, 120 chainClients, 121 accounts, 122 r.balanceCacher, 123 r.omitHistory, 124 r.blockChainState, 125 ) 126 } 127 128 func (r *Reactor) getTransfersByAddress(ctx context.Context, chainID uint64, address common.Address, toBlock *big.Int, 129 limit int64) ([]Transfer, error) { 130 131 if r.strategy != nil { 132 return r.strategy.getTransfersByAddress(ctx, chainID, address, toBlock, limit) 133 } 134 135 return nil, errors.New(ReactorNotStarted) 136 }