From 62410ef6aa93c4da01b24a4d5d91d622db33f6cf Mon Sep 17 00:00:00 2001 From: Tamas Date: Wed, 14 Feb 2024 13:23:34 +0100 Subject: [PATCH] added batch get blocks+logs --- ethrpc.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ ethrpc_test.go | 27 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/ethrpc.go b/ethrpc.go index 8f055a4..52b05cb 100644 --- a/ethrpc.go +++ b/ethrpc.go @@ -583,6 +583,59 @@ func (rpc *EthRPC) BatchGetLogsByRange(from, to int) ([][]Log, error) { return batchedLogs, nil } +func (rpc *EthRPC) BatchGetBlocksAndLogs(numbers ...int) ([]*Block, [][]Log, error) { + var blockRequests []ethRequest + var logRequests []ethRequest + for _, number := range numbers { + blockRequests = append(blockRequests, ethRequest{ + ID: number, + JSONRPC: "2.0", + Method: "eth_getBlockByNumber", + Params: []interface{}{IntToHex(number), true}, + }) + logRequests = append(logRequests, ethRequest{ + ID: number, + JSONRPC: "2.0", + Method: "eth_getLogs", + Params: []interface{}{FilterParams{ + FromBlock: IntToHex(number), + ToBlock: IntToHex(number), + }}, + }) + } + + blockResponses, err := rpc.batchCall(blockRequests) + if err != nil { + return nil, nil, err + } + + logResponses, err := rpc.batchCall(logRequests) + if err != nil { + return nil, nil, err + } + + var blocks []*Block + for _, res := range blockResponses { + var proxy proxyBlockWithTransactions + if err := json.Unmarshal(res, &proxy); err != nil { + return nil, nil, err + } + block := proxy.toBlock() + blocks = append(blocks, &block) + } + + var batchedLogs [][]Log + for _, res := range logResponses { + var logs []Log + if err := json.Unmarshal(res, &logs); err != nil { + return nil, nil, err + } + batchedLogs = append(batchedLogs, logs) + } + + return blocks, batchedLogs, nil +} + func (rpc *EthRPC) batchCall(req []ethRequest) ([]json.RawMessage, error) { body, err := json.Marshal(req) if err != nil { diff --git a/ethrpc_test.go b/ethrpc_test.go index fa1cd23..3b1c9ad 100644 --- a/ethrpc_test.go +++ b/ethrpc_test.go @@ -7,6 +7,7 @@ import ( "math/big" "net/http" "strconv" + "strings" "testing" "github.com/jarcoal/httpmock" @@ -1177,6 +1178,32 @@ func (s *EthRPCTestSuite) TestBatchGetLogsByRange() { s.Require().Nil(err) } +func (s *EthRPCTestSuite) TestBatchGetBlocksAndLogs() { + numbers := []int{3274863, 3274864} + + httpmock.Reset() + + // Mock responder for both block and log requests + httpmock.RegisterResponder("POST", s.rpc.url, func(request *http.Request) (*http.Response, error) { + requestBody := string(s.getBody(request)) + if strings.Contains(requestBody, `"method":"eth_getBlockByNumber"`) { + blockResponseJSON := `[{"jsonrpc":"2.0","id":3274863,"result":{}},{"jsonrpc":"2.0","id":3274864,"result":{}}]` + return httpmock.NewStringResponse(200, blockResponseJSON), nil + } else if strings.Contains(requestBody, `"method":"eth_getLogs"`) { + logResponseJSON := `[{"jsonrpc":"2.0","id":3274863,"result":[]},{"jsonrpc":"2.0","id":3274864,"result":[]}]` + return httpmock.NewStringResponse(200, logResponseJSON), nil + } + return nil, fmt.Errorf("unexpected request") + }) + + blocks, logs, err := s.rpc.BatchGetBlocksAndLogs(numbers...) + + // Assertions + s.Require().Nil(err) + s.Require().NotNil(blocks) + s.Require().NotNil(logs) +} + func TestEthRPCTestSuite(t *testing.T) { suite.Run(t, new(EthRPCTestSuite)) }