github.com/lmittmann/w3@v0.20.0/module/eth/get_logs.go (about)

     1  package eth
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/ethereum/go-ethereum"
     7  	"github.com/ethereum/go-ethereum/core/types"
     8  	"github.com/ethereum/go-ethereum/rpc"
     9  	"github.com/lmittmann/w3/internal/module"
    10  	"github.com/lmittmann/w3/w3types"
    11  )
    12  
    13  // Logs requests the logs of the given ethereum.FilterQuery q.
    14  func Logs(q ethereum.FilterQuery) w3types.RPCCallerFactory[[]types.Log] {
    15  	return &logsFactory{filterQuery: q}
    16  }
    17  
    18  type logsFactory struct {
    19  	// args
    20  	filterQuery ethereum.FilterQuery
    21  
    22  	// returns
    23  	returns *[]types.Log
    24  }
    25  
    26  func (f *logsFactory) Returns(logs *[]types.Log) w3types.RPCCaller {
    27  	f.returns = logs
    28  	return f
    29  }
    30  
    31  // CreateRequest implements the w3types.RequestCreator interface.
    32  func (f *logsFactory) CreateRequest() (rpc.BatchElem, error) {
    33  	arg, err := toFilterArg(f.filterQuery)
    34  	if err != nil {
    35  		return rpc.BatchElem{}, err
    36  	}
    37  
    38  	return rpc.BatchElem{
    39  		Method: "eth_getLogs",
    40  		Args:   []any{arg},
    41  		Result: f.returns,
    42  	}, nil
    43  }
    44  
    45  // HandleResponse implements the w3types.ResponseHandler interface.
    46  func (f *logsFactory) HandleResponse(elem rpc.BatchElem) error {
    47  	if err := elem.Error; err != nil {
    48  		return err
    49  	}
    50  	return nil
    51  }
    52  
    53  func toFilterArg(q ethereum.FilterQuery) (any, error) {
    54  	arg := map[string]any{
    55  		"topics": q.Topics,
    56  	}
    57  	if len(q.Addresses) > 0 {
    58  		arg["address"] = q.Addresses
    59  	}
    60  	if q.BlockHash != nil {
    61  		arg["blockHash"] = *q.BlockHash
    62  		if q.FromBlock != nil || q.ToBlock != nil {
    63  			return nil, fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock")
    64  		}
    65  	} else {
    66  		if q.FromBlock == nil {
    67  			arg["fromBlock"] = "0x0"
    68  		} else {
    69  			arg["fromBlock"] = module.BlockNumberArg(q.FromBlock)
    70  		}
    71  		arg["toBlock"] = module.BlockNumberArg(q.ToBlock)
    72  	}
    73  	return arg, nil
    74  }