diff --git a/op-node/testutils/rpc_err_faker.go b/op-node/testutils/rpc_err_faker.go new file mode 100644 index 0000000000000..c1e9810b4b9b9 --- /dev/null +++ b/op-node/testutils/rpc_err_faker.go @@ -0,0 +1,51 @@ +package testutils + +import ( + "context" + + "github.com/ethereum/go-ethereum/rpc" + + "github.com/ethereum-optimism/optimism/op-node/client" +) + +// RPCErrFaker implements an RPC by wrapping one, but returns an error when prepared with one, to test RPC error handling. +type RPCErrFaker struct { + // RPC to call when no ErrFn is set, or the ErrFn does not return an error + RPC client.RPC + // ErrFn returns an error when the RPC needs to return error upon a call, batch call or subscription. + // The RPC operates without fake errors if the ErrFn is nil, or returns nil. + ErrFn func() error +} + +func (r RPCErrFaker) Close() { + r.RPC.Close() +} + +func (r RPCErrFaker) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return err + } + } + return r.RPC.CallContext(ctx, result, method, args...) +} + +func (r RPCErrFaker) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return err + } + } + return r.RPC.BatchCallContext(ctx, b) +} + +func (r RPCErrFaker) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (*rpc.ClientSubscription, error) { + if r.ErrFn != nil { + if err := r.ErrFn(); err != nil { + return nil, err + } + } + return r.RPC.EthSubscribe(ctx, channel, args...) +} + +var _ client.RPC = (*RPCErrFaker)(nil)