From 816cf344d327132cb28c07fd940fbf46d2f07454 Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Thu, 8 Jan 2026 19:16:46 -0300 Subject: [PATCH] rpc, ethclient, gethclient: make ethclient.Client take an RPCClient interface --- ethclient/ethclient.go | 13 ++++++++++--- ethclient/gethclient/gethclient.go | 4 ++-- rpc/client.go | 5 +++-- rpc/client_test.go | 10 ++++++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 426194b59f..a9601b3b20 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -32,9 +32,16 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +type RPCClient interface { + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error + EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) + Close() +} + // Client defines typed wrappers for the Ethereum RPC API. type Client struct { - c *rpc.Client + c RPCClient } // Dial connects a client to the given URL. @@ -52,7 +59,7 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) { } // NewClient creates a client that uses the given RPC client. -func NewClient(c *rpc.Client) *Client { +func NewClient(c RPCClient) *Client { return &Client{c} } @@ -62,7 +69,7 @@ func (ec *Client) Close() { } // Client gets the underlying RPC client. -func (ec *Client) Client() *rpc.Client { +func (ec *Client) Client() RPCClient { return ec.c } diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index c2013bca2c..ac016b3661 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -198,12 +198,12 @@ func (ec *Client) GetNodeInfo(ctx context.Context) (*p2p.NodeInfo, error) { } // SubscribeFullPendingTransactions subscribes to new pending transactions. -func (ec *Client) SubscribeFullPendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (*rpc.ClientSubscription, error) { +func (ec *Client) SubscribeFullPendingTransactions(ctx context.Context, ch chan<- *types.Transaction) (ethereum.Subscription, error) { return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions", true) } // SubscribePendingTransactions subscribes to new pending transaction hashes. -func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- common.Hash) (*rpc.ClientSubscription, error) { +func (ec *Client) SubscribePendingTransactions(ctx context.Context, ch chan<- common.Hash) (ethereum.Subscription, error) { return ec.c.EthSubscribe(ctx, ch, "newPendingTransactions") } diff --git a/rpc/client.go b/rpc/client.go index 9dc36a6105..c68b5459b3 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -28,6 +28,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/log" ) @@ -482,7 +483,7 @@ func (c *Client) Notify(ctx context.Context, method string, args ...interface{}) } // EthSubscribe registers a subscription under the "eth" namespace. -func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error) { +func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { return c.Subscribe(ctx, "eth", channel, args...) } @@ -498,7 +499,7 @@ func (c *Client) EthSubscribe(ctx context.Context, channel interface{}, args ... // before considering the subscriber dead. The subscription Err channel will receive // ErrSubscriptionQueueOverflow. Use a sufficiently large buffer on the channel or ensure // that the channel usually has at least one reader to prevent this issue. -func (c *Client) Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*ClientSubscription, error) { +func (c *Client) Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (ethereum.Subscription, error) { // Check type of channel first. chanVal := reflect.ValueOf(channel) if chanVal.Kind() != reflect.Chan || chanVal.Type().ChanDir()&reflect.SendDir == 0 { diff --git a/rpc/client_test.go b/rpc/client_test.go index 03a3410537..daf8de3766 100644 --- a/rpc/client_test.go +++ b/rpc/client_test.go @@ -34,6 +34,7 @@ import ( "time" "github.com/davecgh/go-spew/spew" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/log" ) @@ -496,7 +497,7 @@ func TestClientSubscribeClose(t *testing.T) { var ( nc = make(chan int) errc = make(chan error, 1) - sub *ClientSubscription + sub ethereum.Subscription err error ) go func() { @@ -665,7 +666,12 @@ func TestClientSubscriptionUnsubscribeServer(t *testing.T) { // Unsubscribe and check that unsubscribe was called. sub.Unsubscribe() - if !recorder.unsubscribes[sub.subid] { + + clientSub, ok := sub.(*ClientSubscription) + if !ok { + t.Fatal("subscription is not a ClientSubscription") + } + if !recorder.unsubscribes[clientSub.subid] { t.Fatal("client did not call unsubscribe method") } if _, open := <-sub.Err(); open {