github.com/status-im/status-go@v1.1.0/services/wallet/history/transfers_watcher.go (about) 1 package history 2 3 import ( 4 "context" 5 "math/big" 6 7 "github.com/ethereum/go-ethereum/common" 8 "github.com/ethereum/go-ethereum/event" 9 "github.com/ethereum/go-ethereum/log" 10 "github.com/status-im/status-go/services/wallet/async" 11 "github.com/status-im/status-go/services/wallet/transfer" 12 "github.com/status-im/status-go/services/wallet/walletevent" 13 ) 14 15 type TransfersLoadedCb func(chainID uint64, addresses []common.Address, block *big.Int) 16 17 // Watcher executes a given callback whenever an account gets added/removed 18 type Watcher struct { 19 feed *event.Feed 20 group *async.Group 21 callback TransfersLoadedCb 22 } 23 24 func NewWatcher(feed *event.Feed, callback TransfersLoadedCb) *Watcher { 25 return &Watcher{ 26 feed: feed, 27 callback: callback, 28 } 29 } 30 31 func (w *Watcher) Start() { 32 if w.group != nil { 33 return 34 } 35 36 w.group = async.NewGroup(context.Background()) 37 w.group.Add(func(ctx context.Context) error { 38 return watch(ctx, w.feed, w.callback) 39 }) 40 } 41 42 func (w *Watcher) Stop() { 43 if w.group != nil { 44 w.group.Stop() 45 w.group.Wait() 46 w.group = nil 47 } 48 } 49 50 func onTransfersLoaded(callback TransfersLoadedCb, chainID uint64, addresses []common.Address, blockNum *big.Int) { 51 if callback != nil { 52 callback(chainID, addresses, blockNum) 53 } 54 } 55 56 func watch(ctx context.Context, feed *event.Feed, callback TransfersLoadedCb) error { 57 ch := make(chan walletevent.Event, 100) 58 sub := feed.Subscribe(ch) 59 defer sub.Unsubscribe() 60 61 for { 62 select { 63 case <-ctx.Done(): 64 return nil 65 case err := <-sub.Err(): 66 if err != nil { 67 log.Error("history: transfers watcher subscription failed", "error", err) 68 } 69 case ev := <-ch: 70 if ev.Type == transfer.EventNewTransfers { 71 onTransfersLoaded(callback, ev.ChainID, ev.Accounts, ev.BlockNumber) 72 } 73 } 74 } 75 }