Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests to jsonrpc, starting w/ opstack
Browse files Browse the repository at this point in the history
msf committed Jul 26, 2024
1 parent dc987f4 commit ec37fc9
Showing 11 changed files with 3,290 additions and 45 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ test:
CGO_ENABLED=1 go test -timeout=$(TEST_TIMEOUT) -race -bench=. -benchmem -cover ./...

gen-mocks: bin/moq ./client/jsonrpc/ ./client/duneapi/
./bin/moq -pkg jsonrpc_mock -out ./mocks/jsonrpc/httpclient.go ./client/jsonrpc HTTPClient
./bin/moq -pkg jsonrpc_mock -out ./mocks/jsonrpc/rpcnode.go ./client/jsonrpc BlockchainClient
./bin/moq -pkg duneapi_mock -out ./mocks/duneapi/client.go ./client/duneapi BlockchainIngester

9 changes: 0 additions & 9 deletions client/jsonrpc/arbitrum_nitro.go
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"fmt"
"log/slog"
"time"

"github.com/duneanalytics/blockchain-ingester/models"
@@ -18,14 +17,6 @@ type ArbitrumNitroClient struct {

var _ BlockchainClient = &ArbitrumNitroClient{}

func NewArbitrumNitroClient(log *slog.Logger, cfg Config) (*ArbitrumNitroClient, error) {
rpcClient, err := newClient(log.With("module", "jsonrpc"), cfg)
if err != nil {
return nil, err
}
return &ArbitrumNitroClient{*rpcClient}, nil
}

// BlockByNumber returns the block with the given blockNumber.
// it uses 3 different methods to get the block:
// 1. eth_getBlockByNumber
45 changes: 18 additions & 27 deletions client/jsonrpc/client.go
Original file line number Diff line number Diff line change
@@ -29,44 +29,36 @@ const (
)

type rpcClient struct {
client *retryablehttp.Client
cfg Config
log *slog.Logger
bufPool *sync.Pool
cfg Config
client HTTPClient
httpHeaders map[string]string
log *slog.Logger
wrkPool *ants.Pool
}

func NewClient(logger *slog.Logger, cfg Config) (BlockchainClient, error) {
func NewClient(log *slog.Logger, cfg Config) (BlockchainClient, error) {
// use the production http client w/ retries
return NewRPCClient(log, NewHTTPClient(log), cfg)
}

func NewRPCClient(log *slog.Logger, client HTTPClient, cfg Config) (BlockchainClient, error) {
rpcClient, err := newClient(log.With("module", "jsonrpc"), client, cfg)
if err != nil {
return nil, err
}
switch cfg.EVMStack {
case models.OpStack:
return NewOpStackClient(logger, cfg)
return &OpStackClient{*rpcClient}, nil
case models.ArbitrumNitro:
return NewArbitrumNitroClient(logger, cfg)
return &ArbitrumNitroClient{*rpcClient}, nil
default:
return nil, fmt.Errorf("unsupported EVM stack: %s", cfg.EVMStack)
}
}

func newClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:disable-line:unexported-return
client := retryablehttp.NewClient()
client.RetryMax = MaxRetries
client.Logger = log
checkRetry := func(ctx context.Context, resp *http.Response, err error) (bool, error) {
yes, err2 := retryablehttp.DefaultRetryPolicy(ctx, resp, err)
if yes {
if resp == nil {
log.Warn("Retrying request to RPC client", "error", err2)
} else {
log.Warn("Retrying request to RPC client", "statusCode", resp.Status, "error", err2)
}
}
return yes, err2
}
client.CheckRetry = checkRetry
client.Backoff = retryablehttp.LinearJitterBackoff
client.HTTPClient.Timeout = DefaultRequestTimeout

func newClient(log *slog.Logger, client HTTPClient, cfg Config,
) (*rpcClient, error) { // revive:disable-line:unexported-return
if cfg.TotalRPCConcurrency == 0 {
cfg.TotalRPCConcurrency = DefaultMaxRPCConcurrency
}
@@ -98,8 +90,7 @@ func newClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:dis

func (c *rpcClient) LatestBlockNumber() (int64, error) {
buf := c.bufPool.Get().(*bytes.Buffer)
defer c.bufPool.Put(buf)
buf.Reset()
defer c.putBuffer(buf)

err := c.getResponseBody(context.Background(), "eth_blockNumber", []any{}, buf)
if err != nil {
34 changes: 34 additions & 0 deletions client/jsonrpc/httpclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package jsonrpc

import (
"context"
"log/slog"
"net/http"

"github.com/hashicorp/go-retryablehttp"
)

type HTTPClient interface {
Do(req *retryablehttp.Request) (*http.Response, error)
}

func NewHTTPClient(log *slog.Logger) *retryablehttp.Client {
client := retryablehttp.NewClient()
client.RetryMax = MaxRetries
client.Logger = log
checkRetry := func(ctx context.Context, resp *http.Response, err error) (bool, error) {
yes, err2 := retryablehttp.DefaultRetryPolicy(ctx, resp, err)
if yes {
if resp == nil {
log.Warn("Retrying request to RPC client", "error", err2)
} else {
log.Warn("Retrying request to RPC client", "statusCode", resp.Status, "error", err2)
}
}
return yes, err2
}
client.CheckRetry = checkRetry
client.Backoff = retryablehttp.LinearJitterBackoff
client.HTTPClient.Timeout = DefaultRequestTimeout
return client
}
110 changes: 110 additions & 0 deletions client/jsonrpc/httpclient_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package jsonrpc_test

import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"log/slog"
"net/http"
"os"

"github.com/davecgh/go-spew/spew"
"github.com/duneanalytics/blockchain-ingester/client/jsonrpc"
jsonrpc_mock "github.com/duneanalytics/blockchain-ingester/mocks/jsonrpc"
"github.com/duneanalytics/blockchain-ingester/models"
"github.com/hashicorp/go-retryablehttp"
)

type jsonRPCRequest struct {
Method string `json:"method"`
Params []interface{} `json:"params"`
HTTPHeaders http.Header
}

type jsonRPCResponse struct {
Body io.Reader
StatusCode int // optional, default to 200
ContentType string // optional, default to "application/json"
}

type MockedRequest struct {
Req jsonRPCRequest
Resp jsonRPCResponse
}

func MockHTTPRequests(requests []MockedRequest) *jsonrpc_mock.HTTPClientMock {
return &jsonrpc_mock.HTTPClientMock{
DoFunc: func(req *retryablehttp.Request) (*http.Response, error) {
if req.Method != http.MethodPost {
return nil, fmt.Errorf("expected POST method, got %s", req.Method)
}
// we use httpretryable.Client, so we can't use req.Body directly
// we need to read the body and then reset it

body, err := req.BodyBytes()
if err != nil {
return nil, err
}
var jsonReq jsonRPCRequest
if err := json.Unmarshal(body, &jsonReq); err != nil {
return nil, err
}
jsonReqParams := fmt.Sprintf("%+v", jsonReq.Params)
// looking for a matching request
for _, r := range requests {
if r.Req.Method == jsonReq.Method {
// we do this because reflect.DeepEquals() Comparison fails on map[string]any != map[string]string
if jsonReqParams != fmt.Sprintf("%+v", r.Req.Params) {
continue
}
// this is a match, validate registered headers
for k, v := range r.Req.HTTPHeaders {
if req.Header.Get(k) != v[0] {
return nil, fmt.Errorf("expected header %s to be %s, got %s", k, v[0], req.Header.Get(k))
}
}
// all headers match, return the response
resp := &http.Response{
StatusCode: 200,
Body: io.NopCloser(r.Resp.Body),
Header: make(http.Header),
}
if r.Resp.StatusCode != 0 {
resp.StatusCode = r.Resp.StatusCode
}
resp.Header.Set("Content-Type", "application/json")
if r.Resp.ContentType != "" {
resp.Header.Set("Content-Type", r.Resp.ContentType)
}
return resp, nil
}
}
if jsonReq.Method == "eth_blockNumber" {
resp := &http.Response{
StatusCode: 200,
Body: io.NopCloser(bytes.NewReader([]byte(`{"jsonrpc":"2.0","id":1,"result":"0x7a549b"}`))),
}
return resp, nil
}
return nil, fmt.Errorf("no matching request found, req: %+v", jsonReq)
},
}
}

func NewTestLogger() *slog.Logger {
return slog.New(slog.NewTextHandler(io.Discard, nil))
}

func NewTestRPCClient(httpClient jsonrpc.HTTPClient, stack models.EVMStack) (jsonrpc.BlockchainClient, error) {
return jsonrpc.NewRPCClient(NewTestLogger(), httpClient, jsonrpc.Config{EVMStack: stack})
}

func readFileForTest(filename string) *bytes.Buffer {
data, err := os.ReadFile(filename)
if err != nil {
log.Panicf("Failed to read file: %v", err)
}
return bytes.NewBuffer(data)
}
9 changes: 0 additions & 9 deletions client/jsonrpc/opstack.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
"log/slog"
"time"

"github.com/duneanalytics/blockchain-ingester/models"
@@ -17,14 +16,6 @@ type OpStackClient struct {

var _ BlockchainClient = &OpStackClient{}

func NewOpStackClient(log *slog.Logger, cfg Config) (*OpStackClient, error) {
rpcClient, err := newClient(log.With("module", "jsonrpc"), cfg)
if err != nil {
return nil, err
}
return &OpStackClient{*rpcClient}, nil
}

// BlockByNumber returns the block with the given blockNumber.
// it uses 3 different methods to get the block:
// 1. eth_getBlockByNumber
56 changes: 56 additions & 0 deletions client/jsonrpc/opstack_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package jsonrpc_test

import (
"context"
"testing"

"github.com/duneanalytics/blockchain-ingester/models"
"github.com/stretchr/testify/require"
)

func TestOpStackBasic(t *testing.T) {
getBlockByNumberResponse := readFileForTest("testdata/opstack-eth_getBlockByNumber.json")
getBlockReceiptsResponse := readFileForTest("testdata/opstack-eth_getBlockReceipts.json")
debugtraceBlockByNumberResponse := readFileForTest("testdata/opstack-debug_traceBlockByNumber.json")
blockNumberHex := "0x7a549b"
blockNumber := int64(8017051)
httpClientMock := MockHTTPRequests(
[]MockedRequest{
{
Req: jsonRPCRequest{
Method: "eth_getBlockByNumber",
Params: []interface{}{blockNumberHex, true},
},
Resp: jsonRPCResponse{
Body: getBlockByNumberResponse,
},
},
{
Req: jsonRPCRequest{
Method: "eth_getBlockReceipts",
Params: []interface{}{blockNumberHex},
},
Resp: jsonRPCResponse{
Body: getBlockReceiptsResponse,
},
},
{
Req: jsonRPCRequest{
Method: "debug_traceBlockByNumber",
Params: []interface{}{blockNumberHex, map[string]string{"tracer": "callTracer"}},
},
Resp: jsonRPCResponse{
Body: debugtraceBlockByNumberResponse,
},
},
})

opstack, err := NewTestRPCClient(httpClientMock, models.OpStack)
require.NoError(t, err)

block, err := opstack.BlockByNumber(context.Background(), blockNumber)
require.NoError(t, err)
require.NotNil(t, block)
require.Equal(t, blockNumber, block.BlockNumber)
require.False(t, block.Errored())
}
2,667 changes: 2,667 additions & 0 deletions client/jsonrpc/testdata/opstack-debug_traceBlockByNumber.json

Large diffs are not rendered by default.

155 changes: 155 additions & 0 deletions client/jsonrpc/testdata/opstack-eth_getBlockByNumber.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
{
"jsonrpc": "2.0",
"result": {
"baseFeePerGas": "0x13a2",
"blobGasUsed": "0x0",
"difficulty": "0x0",
"excessBlobGas": "0x0",
"extraData": "0x",
"gasLimit": "0x1c9c380",
"gasUsed": "0x442974",
"hash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"logsBloom": "0x00000000000000000000000000000002000000000000000000008000000000000000000000000000000000004000000000000000000000000000000000000000000000000000100000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000002000001000000000000000000100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000",
"miner": "0x4200000000000000000000000000000000000011",
"mixHash": "0x134657ec80b014632c560af436524a999ec3e3961e9911d21fb413f050b12d2f",
"nonce": "0x0000000000000000",
"number": "0x7a549b",
"parentBeaconBlockRoot": "0xd38373593b0d5e9eb20998264fde22b642f6658f7a2975897a7ade285e4b4daf",
"parentHash": "0x98b4922cd437bbd00d09c72eaa4569de934918cb52ddfcf5c765928d86f96306",
"receiptsRoot": "0xaec6d23829974cc7f55ab728fe1e87615d195fc5d0460fd5d42febfd892ba298",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x5fe",
"stateRoot": "0xed73bfa7d6bc0535f1b1318d1ae58983ade52d55c5005c3257fa66e5a930ce09",
"timestamp": "0x664b28d5",
"totalDifficulty": "0x0",
"transactions": [
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"depositReceiptVersion": "0x1",
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
"gas": "0xf4240",
"gasPrice": "0x0",
"hash": "0x6711626fa36243fc18c0f8bac16ab9fcf017c35ec6e340a495ec16151e453757",
"input": "0x440a5e2000004e2000095506000000000000000000000000664b289700000000012fcfc700000000000000000000000000000000000000000000000000000001d6fedf000000000000000000000000000000000000000000000000000000000000000001b7c4005bbc6eee3d76205edaacc42eca5c8fbac4b6b3e0affcd75a864b43bc8000000000000000000000000099199a22125034c808ff20f377d91187e8050f2e",
"mint": "0x0",
"nonce": "0x7a549b",
"r": "0x0",
"s": "0x0",
"sourceHash": "0x5cde6945af90e967d107d56df1c22d0f2844047a38cf655bebfb4ed38e8832a0",
"to": "0x4200000000000000000000000000000000000015",
"transactionIndex": "0x0",
"type": "0x7e",
"v": "0x0",
"value": "0x0"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"chainId": "0x868b",
"from": "0x3342ac381db93eb7768d093e2f1231a2da425d0d",
"gas": "0x5eef",
"gasPrice": "0x10de7b",
"hash": "0x9e88acd51d0f1f2244d278026376105b6b6569b5395c48aa52f2030f866734ef",
"input": "0x646174613a2c7b2270223a226d6f64652d3230222c226f70223a226d696e74222c227469636b223a226d6f646573222c22616d74223a2231227d",
"nonce": "0x24b",
"r": "0x90df8b4c39cc49b799e9eb1efaff48a3037b97cbda14553a221a02b991551c2a",
"s": "0x43abc34cce779a1affc0e9bd5a5a4f213a0361dabaac299cd0668d6c7e9b5a57",
"to": "0x3342ac381db93eb7768d093e2f1231a2da425d0d",
"transactionIndex": "0x1",
"type": "0x0",
"v": "0x10d3a",
"value": "0x0"
},
{
"accessList": [],
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"chainId": "0x868b",
"from": "0x8677f549789e7981f76d4d80c7c54b2dfaa060af",
"gas": "0x22047",
"gasPrice": "0x19a42",
"hash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"input": "0x17835d1c000000000000000000000000000000000000000000000000002f61ab04005df300000000000000000000000000000000000000000000000000000000664b28cf",
"maxFeePerGas": "0x5968564a",
"maxPriorityFeePerGas": "0x186a0",
"nonce": "0x12510",
"r": "0x31ad32847e970beb40026e6f11ebcbc9eb40d0b8cf78976281400cf43c3bfb2b",
"s": "0x153b2f2741f9afceb91b9fd45915673092f52c794a39f7ccc185915d0d76ba5d",
"to": "0x3180341afdd106f14d224ec96c9a17420ab5f33d",
"transactionIndex": "0x2",
"type": "0x2",
"v": "0x0",
"value": "0x0",
"yParity": "0x0"
},
{
"accessList": [],
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"chainId": "0x868b",
"from": "0x5a178ae7d1e3fc42a8425a0c455e3b6c3157ff0c",
"gas": "0x1ab3f00",
"gasPrice": "0x2710",
"hash": "0x310b151c69b810e900cd72c6b0335d8e9dafb783e793eae48b72aa3b6314a704",
"input": "0x00",
"maxFeePerGas": "0x2710",
"maxPriorityFeePerGas": "0x270f",
"nonce": "0x1e59f",
"r": "0x2a307446b54789023633695694108ff5d1c02dc37fa87dd31d7750a134353ee8",
"s": "0x1e5a395c8e0f6943ff04f4d1db127887e6961aed6d8fce80d9a677a73fb065ba",
"to": "0xe6dce473803a7fee2805f02c0140ce01bc738186",
"transactionIndex": "0x3",
"type": "0x2",
"v": "0x0",
"value": "0x0",
"yParity": "0x0"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"chainId": "0x868b",
"from": "0x93df6a148a6dd5b162ae1f49d03a981e13afc8f5",
"gas": "0x1312d00",
"gasPrice": "0x2710",
"hash": "0x27c04bd94b2404b0e9b898394c72cdf95471f2a4a57ca563be44a899d9b91a9a",
"input": "0x00000000",
"nonce": "0x29a2c",
"r": "0xd58aa4ca52e46514b9ceb18502775ac0fb1653721b8fd0fc36cf52c0031b52b",
"s": "0xdf6eea19e8925e5618509d8b1b68d58fb43c70c593a743f1ac712b2cbf9ec2c",
"to": "0x4397da4e02198b79e6934ad10e395d43816b553d",
"transactionIndex": "0x4",
"type": "0x0",
"v": "0x10d3a",
"value": "0x0"
},
{
"accessList": [],
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"chainId": "0x868b",
"from": "0x1e8248888f342a4fdc91b4de3a883193dc8539bb",
"gas": "0x12e1fc0",
"gasPrice": "0x13a3",
"hash": "0x42c16a4a0d2129017f90755da9727d1a77e2d4ae3289489c0ce356b414941746",
"input": "0x4e71d92d",
"maxFeePerGas": "0x5f6084a",
"maxPriorityFeePerGas": "0x1",
"nonce": "0x27320",
"r": "0xce51449548a7d61c6db165e3d03ed629c21733971f1daae3d9f1ac9248733381",
"s": "0x1b9b2dbe8ceed702f54b3c124dfb72405f6ea26357c58a056b983aee4c00a4d0",
"to": "0x2d58e04e43411c58e781339d70f8ebe05aa17b68",
"transactionIndex": "0x5",
"type": "0x2",
"v": "0x0",
"value": "0x0",
"yParity": "0x0"
}
],
"transactionsRoot": "0xb710d62aa870d3c6b90f1ef85e285ac91e23f3bcc61f1d181d22ee884f65bd98",
"uncles": [],
"withdrawals": [],
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
},
"id": 1
}
172 changes: 172 additions & 0 deletions client/jsonrpc/testdata/opstack-eth_getBlockReceipts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{
"jsonrpc": "2.0",
"result": [
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0xcbf7",
"depositNonce": "0x7a549b",
"depositReceiptVersion": "0x1",
"effectiveGasPrice": "0x0",
"from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001",
"gasUsed": "0xcbf7",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x4200000000000000000000000000000000000015",
"transactionHash": "0x6711626fa36243fc18c0f8bac16ab9fcf017c35ec6e340a495ec16151e453757",
"transactionIndex": "0x0",
"type": "0x7e"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0x1219f",
"effectiveGasPrice": "0x10de7b",
"from": "0x3342ac381db93eb7768d093e2f1231a2da425d0d",
"gasUsed": "0x55a8",
"l1Fee": "0x608dd93c8d",
"l1GasPrice": "0x1d6fedf00",
"l1GasUsed": "0xa40",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x3342ac381db93eb7768d093e2f1231a2da425d0d",
"transactionHash": "0x9e88acd51d0f1f2244d278026376105b6b6569b5395c48aa52f2030f866734ef",
"transactionIndex": "0x1",
"type": "0x0"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0x33d7b",
"effectiveGasPrice": "0x19a42",
"from": "0x8677f549789e7981f76d4d80c7c54b2dfaa060af",
"gasUsed": "0x21bdc",
"l1Fee": "0x53e5661f8a",
"l1GasPrice": "0x1d6fedf00",
"l1GasUsed": "0x8e8",
"logs": [
{
"address": "0x3180341afdd106f14d224ec96c9a17420ab5f33d",
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"data": "0x000000000000000000000000cdd475325d6f564d27247d1dddbb0dac6fa0a5cf00000000000000000000000000000000000cea5044471bf5a7169dace880000000000000000000000000000000000000000ced28894f0dac2b3cb76828000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008da",
"logIndex": "0x0",
"removed": false,
"topics": [
"0x23b9387f81fca646aac1dc4487ede045c65f5f7445482906565f01e05afdb3a8"
],
"transactionHash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"transactionIndex": "0x2"
},
{
"address": "0x1d610fd6a8cb065658c7e6ce5ea268310dc8043e",
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"data": "0x000000000000000000000000cdd475325d6f564d27247d1dddbb0dac6fa0a5cf00000000000000000000000000000000000cede883782b9b651fda18380000000000000000000000000000003180341afdd106f14d224ec96c9a17420ab5f33d",
"logIndex": "0x1",
"removed": false,
"topics": [
"0xc37a77b91cc3fc2d0e4b43fd2f347ec67adda10e39215de4742836cc3e42c97a"
],
"transactionHash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"transactionIndex": "0x2"
},
{
"address": "0x3180341afdd106f14d224ec96c9a17420ab5f33d",
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"data": "0x000000000000000000000000420000000000000000000000000000000000000600000000000000000000000000000000000099059e68e694a21e2c04d6800000000000000000000000000000000000000000990249e930e17af3272730000000000000000000000000000000000000000000000000000000000000000000054600000000000000000000000000000000000000000000000000000000000016b8",
"logIndex": "0x2",
"removed": false,
"topics": [
"0x23b9387f81fca646aac1dc4487ede045c65f5f7445482906565f01e05afdb3a8"
],
"transactionHash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"transactionIndex": "0x2"
},
{
"address": "0x1d610fd6a8cb065658c7e6ce5ea268310dc8043e",
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"data": "0x00000000000000000000000042000000000000000000000000000000000000060000000000000000000000000000000000009919122e32544c0b5496f80000000000000000000000000000003180341afdd106f14d224ec96c9a17420ab5f33d",
"logIndex": "0x3",
"removed": false,
"topics": [
"0xc37a77b91cc3fc2d0e4b43fd2f347ec67adda10e39215de4742836cc3e42c97a"
],
"transactionHash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"transactionIndex": "0x2"
}
],
"logsBloom": "0x00000000000000000000000000000002000000000000000000008000000000000000000000000000000000004000000000000000000000000000000000000000000000000000100000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000002000001000000000000000000100100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x3180341afdd106f14d224ec96c9a17420ab5f33d",
"transactionHash": "0x6aef02d81df05983cbd528a7e1d57696cef3f0f3f5f7a8c5a9b1f7d4b6a6d8bd",
"transactionIndex": "0x2",
"type": "0x2"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0x78f1d",
"effectiveGasPrice": "0x2710",
"from": "0x5a178ae7d1e3fc42a8425a0c455e3b6c3157ff0c",
"gasUsed": "0x451a2",
"l1Fee": "0x410e677162",
"l1GasPrice": "0x1d6fedf00",
"l1GasUsed": "0x6e8",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0xe6dce473803a7fee2805f02c0140ce01bc738186",
"transactionHash": "0x310b151c69b810e900cd72c6b0335d8e9dafb783e793eae48b72aa3b6314a704",
"transactionIndex": "0x3",
"type": "0x2"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0x2c6865",
"effectiveGasPrice": "0x2710",
"from": "0x93df6a148a6dd5b162ae1f49d03a981e13afc8f5",
"gasUsed": "0x24d948",
"l1Fee": "0x3eb3879b9d",
"l1GasPrice": "0x1d6fedf00",
"l1GasUsed": "0x6a8",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x4397da4e02198b79e6934ad10e395d43816b553d",
"transactionHash": "0x27c04bd94b2404b0e9b898394c72cdf95471f2a4a57ca563be44a899d9b91a9a",
"transactionIndex": "0x4",
"type": "0x0"
},
{
"blockHash": "0x4dc3e5326b8d6e7eb4d0a9220381d911b09431a2b27ee6ab06a6249a5195f436",
"blockNumber": "0x7a549b",
"contractAddress": null,
"cumulativeGasUsed": "0x442974",
"effectiveGasPrice": "0x13a3",
"from": "0x1e8248888f342a4fdc91b4de3a883193dc8539bb",
"gasUsed": "0x17c10f",
"l1Fee": "0x43da513f3c",
"l1GasPrice": "0x1d6fedf00",
"l1GasUsed": "0x734",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x2d58e04e43411c58e781339d70f8ebe05aa17b68",
"transactionHash": "0x42c16a4a0d2129017f90755da9727d1a77e2d4ae3289489c0ce356b414941746",
"transactionIndex": "0x5",
"type": "0x2"
}
],
"id": 1
}
77 changes: 77 additions & 0 deletions mocks/jsonrpc/httpclient.go

0 comments on commit ec37fc9

Please sign in to comment.