diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index f10626c01f..9edca8ebe3 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/eth/tracers" ) // Client defines typed wrappers for the Ethereum RPC API. @@ -50,11 +51,44 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) { return NewClient(c), nil } +type Client struct { + rpcClient *rpc.Client +} + // NewClient creates a client that uses the given RPC client. func NewClient(c *rpc.Client) *Client { return &Client{c} } +// TraceCall: for call operation +func (c *Client) TraceCall(ctx context.Context, callArgs interface{}) (*tracers.TraceResult, error) { + var result tracers.TraceResult + err := c.rpcClient.CallContext(ctx, &result, "debug_traceCall", callArgs) + return &result, err +} + +// TraceTransaction: fetches a specific transaction +func (c *Client) TraceTransaction(ctx context.Context, txHash string) (*tracers.TraceResult, error) { + var result tracers.TraceResult + err := c.rpcClient.CallContext(ctx, &result, "debug_traceTransaction", txHash, nil) + return &result, err +} + +// TraceBlock: fetches the trace for a specific block +func (c *Client) TraceBlock(ctx context.Context, blockHash string) (*tracers.TraceResult, error) { + var result tracers.TraceResult + err := c.rpcClient.CallContext(ctx, &result, "debug_traceBlock", blockHash) + return &result, err +} + +// TraceChain: fetches the trace for a chain +func (c *Client) TraceChain(ctx context.Context, blockHash string, count int) ([]*tracers.TraceResult, error) { + var result []*tracers.TraceResult + err := c.rpcClient.CallContext(ctx, &result, "debug_traceChain", blockHash, count) + return result, err +} + + // Close closes the underlying RPC connection. func (ec *Client) Close() { ec.c.Close() diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go index 5fc7ed68f9..9cbb01bafb 100644 --- a/ethclient/ethclient_test.go +++ b/ethclient/ethclient_test.go @@ -40,6 +40,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/eth/tracers" ) // Verify that Client implements the ethereum interfaces. @@ -686,3 +687,61 @@ func ExampleRevertErrorData() { // revert: 08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a75736572206572726f72 // message: user error } + +func TestTracing(t *testing.T) { + rpcClient := getRPCClient(t) + client := NewClient(rpcClient) + + t.Run("TraceTransaction", func(t *testing.T) { + txHash := testTx1.Hash() + + result, err := client.TraceTransaction(context.Background(), txHash.Hex()) + if err != nil { + t.Fatalf("Failed to trace transaction: %v", err) + } + + assert.NotNil(t, result, "Trace result should not be nil") + t.Logf("Trace Transaction Result: %+v", result) + }) + + t.Run("TraceCall", func(t *testing.T) { + callArgs := map[string]interface{}{ + "from": testAddr, + "to": revertContractAddr, + "data": revertCode, + } + + result, err := client.TraceCall(context.Background(), callArgs) + if err != nil { + t.Fatalf("Failed to trace call: %v", err) + } + + assert.NotNil(t, result, "Trace result should not be nil") + t.Logf("Trace Call Result: %+v", result) + }) + + t.Run("TraceBlock", func(t *testing.T) { + blockHash := common.HexToHash(testKey) + + result, err := client.TraceBlock(context.Background(), blockHash.Hex()) + if err != nil { + t.Fatalf("Failed to trace block: %v", err) + } + + assert.NotNil(t, result, "Trace result should not be nil") + t.Logf("Trace Block Result: %+v", result) + }) + + t.Run("TraceChain", func(t *testing.T) { + blockHash := common.HexToHash(testKey) + count := 10 + + result, err := client.TraceChain(context.Background(), blockHash.Hex(), count) + if err != nil { + t.Fatalf("Failed to trace chain: %v", err) + } + + assert.NotNil(t, result, "Trace result should not be nil") + t.Logf("Trace Chain Result: %+v", result) + }) +} \ No newline at end of file