diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 390f085677..caa94e577b 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -427,6 +427,36 @@ func (ec *Client) NonceAtHash(ctx context.Context, account common.Address, block // Filters +func (ec *Client) BatchFilterLogs(ctx context.Context, queries []ethereum.FilterQuery) ([]*ethereum.BatchLogsResult, error) { + var b []rpc.BatchElem + var batchResults []*ethereum.BatchLogsResult + + for _, q := range queries { + + var result []*types.Log + arg, err := toFilterArg(q) + if err != nil { + return nil, err + } + + blr := ethereum.BatchLogsResult{ + Logs: result, + Err: nil, + } + batchResults = append(batchResults, &blr) + + b = append(b, rpc.BatchElem{ + Method: "eth_getLogs", + Args: []interface{}{arg}, + Result: result, + Error: err, + }) + } + + err := ec.c.BatchCallContext(ctx, b) + return batchResults, err +} + // FilterLogs executes a filter query. func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { var result []types.Log diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 2f3229cedc..1d96fc76f6 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -294,6 +294,9 @@ func TestEthClient(t *testing.T) { "TransactionSender": { func(t *testing.T) { testTransactionSender(t, client) }, }, + "BatchFilterLogs": { + func(t *testing.T) { batchFilterLogs(t, client) }, + }, } t.Parallel() @@ -760,3 +763,36 @@ func sendTransaction(ec *Client) error { } return ec.SendTransaction(context.Background(), tx) } + +func batchFilterLogs(t *testing.T, client *rpc.Client) { + ec := NewClient(client) + + blockNumber, err := ec.BlockNumber(context.Background()) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + q1 := ethereum.FilterQuery{ + BlockHash: nil, + FromBlock: new(big.Int).SetUint64(0), + ToBlock: new(big.Int).SetUint64(1), + Addresses: []common.Address{{}}, + Topics: nil, + } + + q2 := ethereum.FilterQuery{ + BlockHash: nil, + FromBlock: new(big.Int).SetUint64(1), + ToBlock: new(big.Int).SetUint64(blockNumber), + Addresses: []common.Address{{}}, + Topics: nil, + } + + resp, err := ec.BatchFilterLogs(context.Background(), []ethereum.FilterQuery{q1, q2}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + _ = resp + +} diff --git a/interfaces.go b/interfaces.go index 53e2e3ae16..3d8d9d6823 100644 --- a/interfaces.go +++ b/interfaces.go @@ -187,6 +187,11 @@ type FilterQuery struct { Topics [][]common.Hash } +type BatchLogsResult struct { + Logs []*types.Log + Err error +} + // LogFilterer provides access to contract log events using a one-off query or continuous // event subscription. // @@ -195,6 +200,7 @@ type FilterQuery struct { type LogFilterer interface { FilterLogs(ctx context.Context, q FilterQuery) ([]types.Log, error) SubscribeFilterLogs(ctx context.Context, q FilterQuery, ch chan<- types.Log) (Subscription, error) + BatchFilterLogs(ctx context.Context, queries []FilterQuery) ([]*BatchLogsResult, error) } // TransactionSender wraps transaction sending. The SendTransaction method injects a