github.com/status-im/status-go@v1.1.0/services/rpcfilters/latest_logs.go (about) 1 package rpcfilters 2 3 import ( 4 "context" 5 "math/big" 6 "time" 7 8 ethereum "github.com/ethereum/go-ethereum" 9 "github.com/ethereum/go-ethereum/common/hexutil" 10 "github.com/ethereum/go-ethereum/core/types" 11 "github.com/ethereum/go-ethereum/log" 12 getRpc "github.com/ethereum/go-ethereum/rpc" 13 ) 14 15 // ContextCaller provides CallContext method as ethereums rpc.Client. 16 type ContextCaller interface { 17 CallContext(ctx context.Context, result interface{}, chainID uint64, method string, args ...interface{}) error 18 } 19 20 func pollLogs(client ContextCaller, chainID uint64, f *logsFilter, timeout, period time.Duration) { 21 query := func() { 22 ctx, cancel := context.WithTimeout(f.ctx, timeout) 23 defer cancel() 24 logs, err := getLogs(ctx, client, chainID, f.criteria()) 25 if err != nil { 26 log.Error("Error fetch logs", "criteria", f.crit, "error", err) 27 return 28 } 29 if err := f.add(logs); err != nil { 30 log.Error("Error adding logs", "logs", logs, "error", err) 31 } 32 } 33 query() 34 latest := time.NewTicker(period) 35 defer latest.Stop() 36 for { 37 select { 38 case <-latest.C: 39 query() 40 case <-f.done: 41 log.Debug("Filter was stopped", "ID", f.id, "crit", f.crit) 42 return 43 } 44 } 45 } 46 func getLogs(ctx context.Context, client ContextCaller, chainID uint64, crit ethereum.FilterQuery) (rst []types.Log, err error) { 47 return rst, client.CallContext(ctx, &rst, chainID, "eth_getLogs", toFilterArg(crit)) 48 } 49 50 func toFilterArg(q ethereum.FilterQuery) interface{} { 51 arg := map[string]interface{}{ 52 "fromBlock": toBlockNumArg(q.FromBlock), 53 "toBlock": toBlockNumArg(q.ToBlock), 54 "address": q.Addresses, 55 "topics": q.Topics, 56 } 57 if q.FromBlock == nil { 58 arg["fromBlock"] = "0x0" 59 } 60 return arg 61 } 62 63 func toBlockNumArg(number *big.Int) string { 64 if number == nil || number.Int64() == getRpc.LatestBlockNumber.Int64() { 65 return "latest" 66 } else if number.Int64() == getRpc.PendingBlockNumber.Int64() { 67 return "pending" 68 } 69 return hexutil.EncodeBig(number) 70 }