rpc, ethclient: Add rpc.ClientInterface and use it in ethclient to allow custom rpc client implementation

This commit is contained in:
Lucas ALLOIN 2024-10-19 01:30:24 +02:00
parent b6c62d5887
commit 2092132dd6
No known key found for this signature in database
GPG key ID: F1FB0A930FA025C1
5 changed files with 41 additions and 27 deletions

View file

@ -33,7 +33,7 @@ import (
// Client defines typed wrappers for the Ethereum RPC API. // Client defines typed wrappers for the Ethereum RPC API.
type Client struct { type Client struct {
c *rpc.Client c rpc.ClientInterface
} }
// Dial connects a client to the given URL. // Dial connects a client to the given URL.
@ -51,7 +51,7 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) {
} }
// NewClient creates a client that uses the given RPC client. // NewClient creates a client that uses the given RPC client.
func NewClient(c *rpc.Client) *Client { func NewClient(c rpc.ClientInterface) *Client {
return &Client{c} return &Client{c}
} }
@ -61,7 +61,7 @@ func (ec *Client) Close() {
} }
// Client gets the underlying RPC client. // Client gets the underlying RPC client.
func (ec *Client) Client() *rpc.Client { func (ec *Client) Client() rpc.ClientInterface {
return ec.c return ec.c
} }

View file

@ -302,7 +302,7 @@ func TestEthClient(t *testing.T) {
} }
} }
func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) { func testHeader(t *testing.T, chain []*types.Block, client rpc.ClientInterface) {
tests := map[string]struct { tests := map[string]struct {
block *big.Int block *big.Int
want *types.Header want *types.Header
@ -342,7 +342,7 @@ func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
} }
} }
func testBalanceAt(t *testing.T, client *rpc.Client) { func testBalanceAt(t *testing.T, client rpc.ClientInterface) {
tests := map[string]struct { tests := map[string]struct {
account common.Address account common.Address
block *big.Int block *big.Int
@ -388,7 +388,7 @@ func testBalanceAt(t *testing.T, client *rpc.Client) {
} }
} }
func testTransactionInBlock(t *testing.T, client *rpc.Client) { func testTransactionInBlock(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
// Get current block by number. // Get current block by number.
@ -420,7 +420,7 @@ func testTransactionInBlock(t *testing.T, client *rpc.Client) {
} }
} }
func testChainID(t *testing.T, client *rpc.Client) { func testChainID(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
id, err := ec.ChainID(context.Background()) id, err := ec.ChainID(context.Background())
if err != nil { if err != nil {
@ -431,7 +431,7 @@ func testChainID(t *testing.T, client *rpc.Client) {
} }
} }
func testGetBlock(t *testing.T, client *rpc.Client) { func testGetBlock(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
// Get current block number // Get current block number
@ -476,7 +476,7 @@ func testGetBlock(t *testing.T, client *rpc.Client) {
} }
} }
func testStatusFunctions(t *testing.T, client *rpc.Client) { func testStatusFunctions(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
// Sync progress // Sync progress
@ -539,7 +539,7 @@ func testStatusFunctions(t *testing.T, client *rpc.Client) {
} }
} }
func testCallContractAtHash(t *testing.T, client *rpc.Client) { func testCallContractAtHash(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
// EstimateGas // EstimateGas
@ -566,7 +566,7 @@ func testCallContractAtHash(t *testing.T, client *rpc.Client) {
} }
} }
func testCallContract(t *testing.T, client *rpc.Client) { func testCallContract(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
// EstimateGas // EstimateGas
@ -593,7 +593,7 @@ func testCallContract(t *testing.T, client *rpc.Client) {
} }
} }
func testAtFunctions(t *testing.T, client *rpc.Client) { func testAtFunctions(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1)) block, err := ec.HeaderByNumber(context.Background(), big.NewInt(1))
@ -696,7 +696,7 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
} }
} }
func testTransactionSender(t *testing.T, client *rpc.Client) { func testTransactionSender(t *testing.T, client rpc.ClientInterface) {
ec := NewClient(client) ec := NewClient(client)
ctx := context.Background() ctx := context.Background()

View file

@ -37,11 +37,11 @@ import (
// //
// If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead. // If you want to use the standardized Ethereum RPC functionality, use ethclient.Client instead.
type Client struct { type Client struct {
c *rpc.Client c rpc.ClientInterface
} }
// New creates a client that uses the given RPC client. // New creates a client that uses the given RPC client.
func New(c *rpc.Client) *Client { func New(c rpc.ClientInterface) *Client {
return &Client{c} return &Client{c}
} }

View file

@ -162,7 +162,7 @@ func TestGethClient(t *testing.T) {
} }
} }
func testAccessList(t *testing.T, client *rpc.Client) { func testAccessList(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
// Test transfer // Test transfer
msg := ethereum.CallMsg{ msg := ethereum.CallMsg{
@ -216,7 +216,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
} }
} }
func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) { func testGetProof(t *testing.T, client rpc.ClientInterface, addr common.Address) {
ec := New(client) ec := New(client)
ethcl := ethclient.NewClient(client) ethcl := ethclient.NewClient(client)
result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil) result, err := ec.GetProof(context.Background(), addr, []string{testSlot.String()}, nil)
@ -254,7 +254,7 @@ func testGetProof(t *testing.T, client *rpc.Client, addr common.Address) {
} }
} }
func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) { func testGetProofCanonicalizeKeys(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
// Tests with non-canon input for storage keys. // Tests with non-canon input for storage keys.
@ -284,7 +284,7 @@ func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
} }
} }
func testGetProofNonExistent(t *testing.T, client *rpc.Client) { func testGetProofNonExistent(t *testing.T, client rpc.ClientInterface) {
addr := common.HexToAddress("0x0001") addr := common.HexToAddress("0x0001")
ec := New(client) ec := New(client)
result, err := ec.GetProof(context.Background(), addr, nil, nil) result, err := ec.GetProof(context.Background(), addr, nil, nil)
@ -316,7 +316,7 @@ func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
} }
} }
func testGCStats(t *testing.T, client *rpc.Client) { func testGCStats(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
_, err := ec.GCStats(context.Background()) _, err := ec.GCStats(context.Background())
if err != nil { if err != nil {
@ -324,7 +324,7 @@ func testGCStats(t *testing.T, client *rpc.Client) {
} }
} }
func testMemStats(t *testing.T, client *rpc.Client) { func testMemStats(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
stats, err := ec.MemStats(context.Background()) stats, err := ec.MemStats(context.Background())
if err != nil { if err != nil {
@ -335,7 +335,7 @@ func testMemStats(t *testing.T, client *rpc.Client) {
} }
} }
func testGetNodeInfo(t *testing.T, client *rpc.Client) { func testGetNodeInfo(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
info, err := ec.GetNodeInfo(context.Background()) info, err := ec.GetNodeInfo(context.Background())
if err != nil { if err != nil {
@ -347,7 +347,7 @@ func testGetNodeInfo(t *testing.T, client *rpc.Client) {
} }
} }
func testSetHead(t *testing.T, client *rpc.Client) { func testSetHead(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
err := ec.SetHead(context.Background(), big.NewInt(0)) err := ec.SetHead(context.Background(), big.NewInt(0))
if err != nil { if err != nil {
@ -355,7 +355,7 @@ func testSetHead(t *testing.T, client *rpc.Client) {
} }
} }
func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) { func testSubscribePendingTransactions(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
ethcl := ethclient.NewClient(client) ethcl := ethclient.NewClient(client)
// Subscribe to Transactions // Subscribe to Transactions
@ -389,7 +389,7 @@ func testSubscribePendingTransactions(t *testing.T, client *rpc.Client) {
} }
} }
func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) { func testSubscribeFullPendingTransactions(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
ethcl := ethclient.NewClient(client) ethcl := ethclient.NewClient(client)
// Subscribe to Transactions // Subscribe to Transactions
@ -423,7 +423,7 @@ func testSubscribeFullPendingTransactions(t *testing.T, client *rpc.Client) {
} }
} }
func testCallContract(t *testing.T, client *rpc.Client) { func testCallContract(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
msg := ethereum.CallMsg{ msg := ethereum.CallMsg{
From: testAddr, From: testAddr,
@ -533,7 +533,7 @@ func TestBlockOverridesMarshal(t *testing.T) {
} }
} }
func testCallContractWithBlockOverrides(t *testing.T, client *rpc.Client) { func testCallContractWithBlockOverrides(t *testing.T, client rpc.ClientInterface) {
ec := New(client) ec := New(client)
msg := ethereum.CallMsg{ msg := ethereum.CallMsg{
From: testAddr, From: testAddr,

View file

@ -75,6 +75,20 @@ type BatchElem struct {
Error error Error error
} }
// ClientInterface is the interface that an EVM rpc client must implement.
type ClientInterface interface {
Call(result interface{}, method string, args ...interface{}) error
CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error
BatchCall(b []BatchElem) error
BatchCallContext(ctx context.Context, b []BatchElem) error
Notify(ctx context.Context, method string, args ...interface{}) error
EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error)
ShhSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*ClientSubscription, error)
Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*ClientSubscription, error)
SupportsSubscriptions() bool
Close()
}
// Client represents a connection to an RPC server. // Client represents a connection to an RPC server.
type Client struct { type Client struct {
idgen func() ID // for subscriptions idgen func() ID // for subscriptions