diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index aeb0db11ed..5008378da6 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -124,7 +124,7 @@ func (ec *Client) PeerCount(ctx context.Context) (uint64, error) { // BlockReceipts returns the receipts of a given block number or hash. func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { var r []*types.Receipt - err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash) + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash.String()) if err == nil && r == nil { return nil, ethereum.NotFound } diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 7d71994c79..302ccf2e16 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -1001,45 +1001,3 @@ func TestSimulateV1WithBlockNumberOrHash(t *testing.T) { t.Fatalf("expected 1 block result, got %d", len(results)) } } - -func TestBlockReceiptsPreservesRequireCanonical(t *testing.T) { - server := rpc.NewServer() - service := &testBlockReceiptsService{} - if err := server.RegisterName("eth", service); err != nil { - t.Fatalf("failed to register test service: %v", err) - } - defer server.Stop() - - rpcClient := rpc.DialInProc(server) - defer rpcClient.Close() - - client := ethclient.NewClient(rpcClient) - defer client.Close() - - hash := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") - arg := rpc.BlockNumberOrHashWithHash(hash, true) - - if _, err := client.BlockReceipts(context.Background(), arg); err != nil { - t.Fatalf("BlockReceipts returned error: %v", err) - } - if !service.called { - t.Fatalf("expected GetBlockReceipts to be called") - } - if !service.lastArg.RequireCanonical { - t.Fatalf("requireCanonical flag was not preserved") - } - if service.lastArg.BlockHash == nil || *service.lastArg.BlockHash != hash { - t.Fatalf("unexpected block hash: %v", service.lastArg.BlockHash) - } -} - -type testBlockReceiptsService struct { - lastArg rpc.BlockNumberOrHash - called bool -} - -func (s *testBlockReceiptsService) GetBlockReceipts(ctx context.Context, arg rpc.BlockNumberOrHash) ([]*types.Receipt, error) { - s.lastArg = arg - s.called = true - return []*types.Receipt{}, nil -} diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 6a0f5eb312..9c732ea473 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -166,6 +166,17 @@ func (ec *Client) CallContractWithBlockOverrides(ctx context.Context, msg ethere return hex, err } +// BlockReceipts returns the receipts of a given block number or hash. +// This wrapper preserves geth-specific flags such as requireCanonical. +func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + var r []*types.Receipt + err := ec.c.CallContext(ctx, &r, "eth_getBlockReceipts", blockNrOrHash) + if err == nil && r == nil { + return nil, ethereum.NotFound + } + return r, err +} + // GCStats retrieves the current garbage collection stats from a geth node. func (ec *Client) GCStats(ctx context.Context) (*debug.GCStats, error) { var result debug.GCStats diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 0eed63cacf..47a5cd312f 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -620,3 +620,44 @@ func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) { t.Fatalf("unexpected result: %x", res) } } + +func TestGethClientBlockReceiptsPreservesRequireCanonical(t *testing.T) { + server := rpc.NewServer() + service := &testGethBlockReceiptsService{} + if err := server.RegisterName("eth", service); err != nil { + t.Fatalf("failed to register test service: %v", err) + } + defer server.Stop() + + rpcClient := rpc.DialInProc(server) + defer rpcClient.Close() + + client := New(rpcClient) + + hash := common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111") + arg := rpc.BlockNumberOrHashWithHash(hash, true) + + if _, err := client.BlockReceipts(context.Background(), arg); err != nil { + t.Fatalf("BlockReceipts returned error: %v", err) + } + if !service.called { + t.Fatalf("expected GetBlockReceipts to be called") + } + if !service.lastArg.RequireCanonical { + t.Fatalf("requireCanonical flag was not preserved") + } + if service.lastArg.BlockHash == nil || *service.lastArg.BlockHash != hash { + t.Fatalf("unexpected block hash: %v", service.lastArg.BlockHash) + } +} + +type testGethBlockReceiptsService struct { + lastArg rpc.BlockNumberOrHash + called bool +} + +func (s *testGethBlockReceiptsService) GetBlockReceipts(ctx context.Context, arg rpc.BlockNumberOrHash) ([]*types.Receipt, error) { + s.lastArg = arg + s.called = true + return []*types.Receipt{}, nil +}