From bec4a96a1e2eac764149b30625ab983402a81ce9 Mon Sep 17 00:00:00 2001 From: ddomeke Date: Mon, 3 Nov 2025 14:58:44 +0300 Subject: [PATCH 1/6] chain id info added to err log --- etherclient/backoff.go | 8 ++++++-- etherclient/client.go | 13 +++++++++++-- etherclient/errors.go | 6 +++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/etherclient/backoff.go b/etherclient/backoff.go index 3bd881b..951d609 100644 --- a/etherclient/backoff.go +++ b/etherclient/backoff.go @@ -69,10 +69,14 @@ func (ec *etherClient) withBackoff( // Move onto the next provider. ec.provider.Next() } - return handleRetryErr(ctx, method, opErr) + return handleRetryErr(ctx, method, ec.chainID, opErr) }, bo) if err != nil { - logrus.WithError(err).WithField("method", method).Error("retry failed with error") + logger := logrus.WithError(err).WithField("method", method) + if ec.chainID != nil { + logger = logger.WithField("chainID", ec.chainID.String()) + } + logger.Error("retry failed with error") } return err } diff --git a/etherclient/client.go b/etherclient/client.go index eaa6cd9..d46724a 100644 --- a/etherclient/client.go +++ b/etherclient/client.go @@ -86,6 +86,8 @@ type etherClient struct { retryInterval time.Duration metricsHandler func(rpcHost, clientMethod string, err error) + + chainID *big.Int } var _ EtherClient = ðerClient{} @@ -111,10 +113,17 @@ func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { } clients = append(clients, ðClientWrapper{url: rawurl, Client: c}) } - return ðerClient{ + ec := ðerClient{ provider: provider.NewRingProvider(clients...), retryInterval: defaultRetryInterval, - }, nil + } + + chainID, err := ec.ChainID(ctx) + if err == nil { + ec.chainID = chainID + } + + return ec, nil } func (ec *etherClient) SetRetryInterval(d time.Duration) { diff --git a/etherclient/errors.go b/etherclient/errors.go index 182a584..a9dc275 100644 --- a/etherclient/errors.go +++ b/etherclient/errors.go @@ -2,6 +2,7 @@ package etherclient import ( "context" + "math/big" "strings" "github.com/cenkalti/backoff" @@ -32,7 +33,7 @@ func isPermanentError(err error) bool { return false } -func handleRetryErr(ctx context.Context, method string, err error) error { +func handleRetryErr(ctx context.Context, method string, chainID *big.Int, err error) error { if err == nil { return nil } @@ -40,6 +41,9 @@ func handleRetryErr(ctx context.Context, method string, err error) error { if len(method) > 0 { logger = logger.WithField("method", method) } + if chainID != nil { + logger = logger.WithField("chainID", chainID.String()) + } if isPermanentError(err) { logger.WithError(err).Error("backoff permanent error") return backoff.Permanent(err) From 9ceaf15a51df57deecacf4ccb9ff7e29431d310a Mon Sep 17 00:00:00 2001 From: ddomeke Date: Tue, 4 Nov 2025 16:21:07 +0300 Subject: [PATCH 2/6] chain id added to dial context --- etherclient/client.go | 13 +++++++++---- scripts/raw-txs/main.go | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/etherclient/client.go b/etherclient/client.go index d46724a..f2218bb 100644 --- a/etherclient/client.go +++ b/etherclient/client.go @@ -104,7 +104,8 @@ func (ecw *ethClientWrapper) GetURL() string { // NewRetrierClient dials all given URLs and creates a client that works with multiple clients // and a backoff logic. -func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { +// If chainID is provided, it will be used directly. Otherwise, it will be fetched from the RPC. +func DialContext(ctx context.Context, chainID *big.Int, rawurls ...string) (*etherClient, error) { var clients []*ethClientWrapper for _, rawurl := range rawurls { c, err := ethclient.DialContext(ctx, rawurl) @@ -116,11 +117,15 @@ func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { ec := ðerClient{ provider: provider.NewRingProvider(clients...), retryInterval: defaultRetryInterval, + chainID: chainID, } - chainID, err := ec.ChainID(ctx) - if err == nil { - ec.chainID = chainID + // If chainID was not provided, fetch it from the RPC + if ec.chainID == nil { + fetchedChainID, err := ec.ChainID(ctx) + if err == nil { + ec.chainID = fetchedChainID + } } return ec, nil diff --git a/scripts/raw-txs/main.go b/scripts/raw-txs/main.go index 2c8c9aa..c80b085 100644 --- a/scripts/raw-txs/main.go +++ b/scripts/raw-txs/main.go @@ -19,7 +19,7 @@ var env Env func main() { envconfig.MustProcess("", &env) - ethClient, err := etherclient.DialContext(context.Background(), env.JSONRPCURL) + ethClient, err := etherclient.DialContext(context.Background(), nil, env.JSONRPCURL) utils.FatalIfError(err) blockNum, err := ethClient.BlockNumber(context.Background()) From e212461c4b2e4d1a5ececde849c1f7e8fd8a32ef Mon Sep 17 00:00:00 2001 From: ddomeke Date: Tue, 4 Nov 2025 17:25:37 +0300 Subject: [PATCH 3/6] set chain added instead of paasing as a param --- etherclient/client.go | 19 ++++++++++--------- scripts/raw-txs/main.go | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/etherclient/client.go b/etherclient/client.go index f2218bb..eb04fd0 100644 --- a/etherclient/client.go +++ b/etherclient/client.go @@ -58,6 +58,7 @@ type EtherClient interface { SetRetryInterval(d time.Duration) SetMetricsHandler(h func(rpcHost, clientMethod string, err error)) + SetChainID(chainID *big.Int) } type Extras interface { @@ -104,8 +105,7 @@ func (ecw *ethClientWrapper) GetURL() string { // NewRetrierClient dials all given URLs and creates a client that works with multiple clients // and a backoff logic. -// If chainID is provided, it will be used directly. Otherwise, it will be fetched from the RPC. -func DialContext(ctx context.Context, chainID *big.Int, rawurls ...string) (*etherClient, error) { +func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { var clients []*ethClientWrapper for _, rawurl := range rawurls { c, err := ethclient.DialContext(ctx, rawurl) @@ -117,15 +117,12 @@ func DialContext(ctx context.Context, chainID *big.Int, rawurls ...string) (*eth ec := ðerClient{ provider: provider.NewRingProvider(clients...), retryInterval: defaultRetryInterval, - chainID: chainID, } - // If chainID was not provided, fetch it from the RPC - if ec.chainID == nil { - fetchedChainID, err := ec.ChainID(ctx) - if err == nil { - ec.chainID = fetchedChainID - } + // Try to fetch chainID from the RPC + chainID, err := ec.ChainID(ctx) + if err == nil { + ec.chainID = chainID } return ec, nil @@ -139,6 +136,10 @@ func (ec *etherClient) SetMetricsHandler(h func(rpcHost, clientMethod string, er ec.metricsHandler = h } +func (ec *etherClient) SetChainID(chainID *big.Int) { + ec.chainID = chainID +} + func (ec *etherClient) Client() *rpc.Client { return ec.provider.Provide().Client.Client() } diff --git a/scripts/raw-txs/main.go b/scripts/raw-txs/main.go index c80b085..2c8c9aa 100644 --- a/scripts/raw-txs/main.go +++ b/scripts/raw-txs/main.go @@ -19,7 +19,7 @@ var env Env func main() { envconfig.MustProcess("", &env) - ethClient, err := etherclient.DialContext(context.Background(), nil, env.JSONRPCURL) + ethClient, err := etherclient.DialContext(context.Background(), env.JSONRPCURL) utils.FatalIfError(err) blockNum, err := ethClient.BlockNumber(context.Background()) From a08c59f74c837fd581da6541b8213d51f859524a Mon Sep 17 00:00:00 2001 From: ddomeke Date: Tue, 4 Nov 2025 17:39:14 +0300 Subject: [PATCH 4/6] set chainid mock added --- etherclient/mocks/mock_client.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/etherclient/mocks/mock_client.go b/etherclient/mocks/mock_client.go index 325dac2..ce9e8ac 100644 --- a/etherclient/mocks/mock_client.go +++ b/etherclient/mocks/mock_client.go @@ -1192,6 +1192,18 @@ func (mr *MockEtherClientMockRecorder) SendTransaction(ctx, tx interface{}) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendTransaction", reflect.TypeOf((*MockEtherClient)(nil).SendTransaction), ctx, tx) } +// SetChainID mocks base method. +func (m *MockEtherClient) SetChainID(chainID *big.Int) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetChainID", chainID) +} + +// SetChainID indicates an expected call of SetChainID. +func (mr *MockEtherClientMockRecorder) SetChainID(chainID interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetChainID", reflect.TypeOf((*MockEtherClient)(nil).SetChainID), chainID) +} + // SetMetricsHandler mocks base method. func (m *MockEtherClient) SetMetricsHandler(h func(string, string, error)) { m.ctrl.T.Helper() From 40c81537b81710eb8b6739e041fd76f9a0d12ad7 Mon Sep 17 00:00:00 2001 From: ddomeke Date: Wed, 5 Nov 2025 10:17:23 +0300 Subject: [PATCH 5/6] ctxWithTimeout added --- etherclient/client.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/etherclient/client.go b/etherclient/client.go index eb04fd0..3308d96 100644 --- a/etherclient/client.go +++ b/etherclient/client.go @@ -119,11 +119,16 @@ func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { retryInterval: defaultRetryInterval, } - // Try to fetch chainID from the RPC - chainID, err := ec.ChainID(ctx) + // Try to fetch chainID from the RPC with a short timeout + // to avoid blocking DialContext for too long + ctxWithTimeout, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + chainID, err := ec.ChainID(ctxWithTimeout) if err == nil { ec.chainID = chainID } + // If ChainID fails here, it can be set later via SetChainID return ec, nil } From a2d224927e84522ffefe367be8b3499c847e2b59 Mon Sep 17 00:00:00 2001 From: ddomeke Date: Wed, 5 Nov 2025 10:38:07 +0300 Subject: [PATCH 6/6] rpc chainid call removed --- etherclient/client.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/etherclient/client.go b/etherclient/client.go index 3308d96..14733a8 100644 --- a/etherclient/client.go +++ b/etherclient/client.go @@ -119,17 +119,6 @@ func DialContext(ctx context.Context, rawurls ...string) (*etherClient, error) { retryInterval: defaultRetryInterval, } - // Try to fetch chainID from the RPC with a short timeout - // to avoid blocking DialContext for too long - ctxWithTimeout, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - - chainID, err := ec.ChainID(ctxWithTimeout) - if err == nil { - ec.chainID = chainID - } - // If ChainID fails here, it can be set later via SetChainID - return ec, nil }