@lido-nestjs/execution 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var tslib = require('tslib');
6
4
  var common = require('@nestjs/common');
7
5
  var extendedJsonRpcBatchProvider = require('./provider/extended-json-rpc-batch-provider.js');
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var logger = require('@ethersproject/logger');
6
4
 
7
5
  const nonRetryableErrors = [
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ /**
4
+ * EventEmitter with lazy event creation.
5
+ * The callback is only called if there are listeners for the event.
6
+ */
7
+ export declare class LazyEventEmitter extends EventEmitter {
8
+ emitLazy<T>(eventName: string, createEvent: () => T): boolean;
9
+ }
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var events = require('events');
4
+
5
+ /**
6
+ * EventEmitter with lazy event creation.
7
+ * The callback is only called if there are listeners for the event.
8
+ */
9
+ class LazyEventEmitter extends events.EventEmitter {
10
+ emitLazy(eventName, createEvent) {
11
+ if (this.listenerCount(eventName) > 0) {
12
+ return this.emit(eventName, createEvent());
13
+ }
14
+ return false;
15
+ }
16
+ }
17
+
18
+ exports.LazyEventEmitter = LazyEventEmitter;
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  const IP_V4_REGEX = new RegExp(/^(?<domain>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::(?<port>\d+))?/i);
6
4
  const DOMAIN_REGEX = new RegExp(/^(?<protocol>https?:\/\/)(?=(?<fqdn>[^:/]+))(?:(?<service>www|ww\d|cdn|ftp|mail|pop\d?|ns\d?|git)\.)?(?:(?<subdomain>[^:/]+)\.)*(?<domain>[^:/]+\.[a-z0-9]+)(?::(?<port>\d+))?(?<path>\/[^?]*)?(?:\?(?<query>[^#]*))?(?:#(?<hash>.*))?/i);
7
5
  const networksEqual = (networkA, networkB) => {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var queue = require('./queue.js');
6
6
 
7
7
  /* eslint-disable @typescript-eslint/ban-types */
8
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
9
  function pLimit(concurrency) {
9
10
  if (!((Number.isInteger(concurrency) ||
10
11
  concurrency === Number.POSITIVE_INFINITY) &&
@@ -62,4 +63,4 @@ function pLimit(concurrency) {
62
63
  return generator;
63
64
  }
64
65
 
65
- exports["default"] = pLimit;
66
+ exports.default = pLimit;
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  class Queue {
6
4
  constructor() {
7
5
  this._store = [];
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var sleep = require('./sleep.js');
6
4
 
7
5
  const retrier = (logger, defaultMaxRetryCount = 3, defaultMinBackoffMs = 1000, defaultMaxBackoffMs = 60000, defaultLogWarning = false, defaultErrorFilter) => {
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
4
 
7
5
  exports.sleep = sleep;
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  const FALLBACK_PROVIDER_MODULE_OPTIONS = Symbol('fallback-provider-module-options');
6
4
  const BATCH_PROVIDER_MODULE_OPTIONS = Symbol('batch-provider-module-options');
7
5
 
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  class AllProvidersFailedError extends Error {
6
4
  constructor(message) {
7
5
  super(message);
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  exports.ErrorCode = void 0;
6
4
  (function (ErrorCode) {
7
5
  ErrorCode["UNEXPECTED_BATCH_RESULT"] = "UNEXPECTED_BATCH_RESULT";
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  class FetchError extends Error {
6
4
  constructor(message) {
7
5
  super(message);
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  class NoNewBlocksWhilePollingError extends Error {
6
4
  constructor(message, latestObservedBlockNumber) {
7
5
  super(message);
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  class RequestTimeoutError extends Error {
6
4
  constructor(message, timeoutMs) {
7
5
  super(message);
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  /**
6
4
  * Thrown when waitForTransactionWithFallback times out.
7
5
  * lastError distinguishes network issues (present) from slow tx (null).
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  async function getDebugTraceBlockByHash(blockHash, traceConfig) {
6
4
  await this.getNetwork();
7
5
  return (await this.perform('getDebugTraceBlockByHash', {
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var bignumber = require('@ethersproject/bignumber');
6
4
  var bytes = require('@ethersproject/bytes');
7
5
  var formatBlockNumber = require('./format-block-number.js');
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var bytes = require('@ethersproject/bytes');
6
4
 
7
5
  const formatBlockNumber = (blockNumber) => {
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var providers = require('@ethersproject/providers');
6
4
 
7
5
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -1,6 +1,6 @@
1
1
  import { SimpleFallbackJsonRpcBatchProvider } from '../provider/simple-fallback-json-rpc-batch-provider';
2
2
  import { AllProvidersFailedError } from '../error';
3
- import { ExtendedJsonRpcBatchProvider, JsonRpcRequest, JsonRpcResponse } from '../provider/extended-json-rpc-batch-provider';
3
+ import { ExtendedJsonRpcBatchProvider, JsonRpcRequest } from '../provider/extended-json-rpc-batch-provider';
4
4
  export declare type FallbackProviderRequestFailedAllEvent = {
5
5
  action: 'fallback-provider:request:failed:all';
6
6
  provider: SimpleFallbackJsonRpcBatchProvider;
@@ -29,7 +29,6 @@ export declare type ProviderResponseBatchedErrorEvent = {
29
29
  export declare type ProviderResponseBatchedEvent = {
30
30
  action: 'provider:response-batched';
31
31
  request: JsonRpcRequest[];
32
- response: JsonRpcResponse[] | JsonRpcResponse;
33
32
  provider: ExtendedJsonRpcBatchProvider;
34
33
  domain: string;
35
34
  };
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var tslib = require('tslib');
6
4
  var common = require('@nestjs/common');
7
5
  var extendedJsonRpcBatchProvider = require('./provider/extended-json-rpc-batch-provider.js');
package/dist/index.js CHANGED
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var extendedJsonRpcBatchProvider = require('./provider/extended-json-rpc-batch-provider.js');
6
4
  var simpleFallbackJsonRpcBatchProvider = require('./provider/simple-fallback-json-rpc-batch-provider.js');
7
5
  var queue = require('./common/queue.js');
@@ -16,20 +14,20 @@ var transactionWaitTimeout_error = require('./error/transaction-wait-timeout.err
16
14
 
17
15
 
18
16
 
19
- Object.defineProperty(exports, 'ExtendedJsonRpcBatchProvider', {
17
+ Object.defineProperty(exports, "ExtendedJsonRpcBatchProvider", {
20
18
  enumerable: true,
21
19
  get: function () { return extendedJsonRpcBatchProvider.ExtendedJsonRpcBatchProvider; }
22
20
  });
23
- Object.defineProperty(exports, 'SimpleFallbackJsonRpcBatchProvider', {
21
+ Object.defineProperty(exports, "SimpleFallbackJsonRpcBatchProvider", {
24
22
  enumerable: true,
25
23
  get: function () { return simpleFallbackJsonRpcBatchProvider.SimpleFallbackJsonRpcBatchProvider; }
26
24
  });
27
25
  exports.Queue = queue.Queue;
28
- Object.defineProperty(exports, 'FallbackProviderModule', {
26
+ Object.defineProperty(exports, "FallbackProviderModule", {
29
27
  enumerable: true,
30
28
  get: function () { return fallbackProvider_module.FallbackProviderModule; }
31
29
  });
32
- Object.defineProperty(exports, 'BatchProviderModule', {
30
+ Object.defineProperty(exports, "BatchProviderModule", {
33
31
  enumerable: true,
34
32
  get: function () { return batchProvider_module.BatchProviderModule; }
35
33
  });
@@ -10,8 +10,9 @@ import { BlockTag } from '../ethers/block-tag';
10
10
  import { MiddlewareCallback, MiddlewareService } from '@lido-nestjs/middleware';
11
11
  import { FeeHistory } from '../ethers/fee-history';
12
12
  import { TraceConfig, TraceResult } from '../interfaces/debug-traces';
13
+ import { LazyEventEmitter } from '../common/lazy-event-emitter';
13
14
  import { ProviderEvents } from '../events';
14
- export interface ExtendedJsonRpcBatchProviderEventEmitter extends NodeJS.EventEmitter {
15
+ export interface ExtendedJsonRpcBatchProviderEventEmitter extends LazyEventEmitter {
15
16
  on(eventName: 'rpc', listener: (event: ProviderEvents) => void): this;
16
17
  once(eventName: 'rpc', listener: (event: ProviderEvents) => void): this;
17
18
  addListener(eventName: 'rpc', listener: (event: ProviderEvents) => void): this;
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var tslib = require('tslib');
6
4
  var properties = require('@ethersproject/properties');
7
5
  var web = require('@ethersproject/web');
@@ -16,7 +14,7 @@ var feeHistory = require('../ethers/fee-history.js');
16
14
  var errorCodes = require('../error/codes/error-codes.js');
17
15
  var debugTraceBlockByHash = require('../ethers/debug-trace-block-by-hash.js');
18
16
  var networks = require('../common/networks.js');
19
- var events = require('events');
17
+ var lazyEventEmitter = require('../common/lazy-event-emitter.js');
20
18
 
21
19
  exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extends providers.JsonRpcProvider {
22
20
  constructor(url, network, requestPolicy, fetchMiddlewares = []) {
@@ -24,14 +22,14 @@ exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extend
24
22
  this._batchAggregator = null;
25
23
  this._queue = new queue.Queue();
26
24
  this._tickCounter = 0;
27
- this._eventEmitter = new events.EventEmitter();
25
+ this._eventEmitter = new lazyEventEmitter.LazyEventEmitter();
28
26
  this._domain = networks.getConnectionFQDN(url);
29
27
  this._requestPolicy = requestPolicy !== null && requestPolicy !== void 0 ? requestPolicy : {
30
28
  jsonRpcMaxBatchSize: 200,
31
29
  maxConcurrentRequests: 5,
32
30
  batchAggregationWaitMs: 10,
33
31
  };
34
- this._concurrencyLimiter = promiseLimit["default"](this._requestPolicy.maxConcurrentRequests);
32
+ this._concurrencyLimiter = promiseLimit.default(this._requestPolicy.maxConcurrentRequests);
35
33
  this._fetchMiddlewareService = new middleware.MiddlewareService({
36
34
  middlewares: fetchMiddlewares,
37
35
  });
@@ -51,13 +49,12 @@ exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extend
51
49
  // if queue size is less then 'jsonRpcMaxBatchSize' - dequeue remaining elements
52
50
  const batch = this._queue.dequeueMultiple(this._requestPolicy.jsonRpcMaxBatchSize);
53
51
  const batchRequest = batch.map((intent) => intent.request);
54
- const event = {
52
+ this._eventEmitter.emitLazy('rpc', () => ({
55
53
  action: 'provider:request-batched',
56
54
  request: properties.deepCopy(batchRequest),
57
55
  provider: this,
58
56
  domain: this._domain,
59
- };
60
- this._eventEmitter.emit('rpc', event);
57
+ }));
61
58
  this._concurrencyLimiter(() => {
62
59
  return this._fetchMiddlewareService.go(() => this.fetchJson(this.connection, JSON.stringify(batchRequest)), {
63
60
  provider: this,
@@ -66,14 +63,12 @@ exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extend
66
63
  })
67
64
  .then((batchResult) => {
68
65
  var _a;
69
- const event = {
66
+ this._eventEmitter.emitLazy('rpc', () => ({
70
67
  action: 'provider:response-batched',
71
68
  request: properties.deepCopy(batchRequest),
72
- response: properties.deepCopy(batchResult),
73
69
  provider: this,
74
70
  domain: this._domain,
75
- };
76
- this._eventEmitter.emit('rpc', event);
71
+ }));
77
72
  if (!Array.isArray(batchResult)) {
78
73
  const errMessage = 'Unexpected batch result.';
79
74
  const jsonRpcErrorMessage = (_a = batchResult.error) === null || _a === void 0 ? void 0 : _a.message;
@@ -96,7 +91,11 @@ exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extend
96
91
  if (!payload) {
97
92
  const error = new fetch_error.FetchError(`Partial payload batch result. Response ${inflightRequest.request.id} not found`);
98
93
  error.code = errorCodes.ErrorCode.PARTIAL_BATCH_RESULT;
99
- error.data = batchResult;
94
+ error.data = {
95
+ requestedId: inflightRequest.request.id,
96
+ receivedIds: batchResult.map((r) => r.id),
97
+ batchSize: batchResult.length,
98
+ };
100
99
  inflightRequest.reject(error);
101
100
  }
102
101
  else if (payload.error) {
@@ -110,28 +109,26 @@ exports.ExtendedJsonRpcBatchProvider = class ExtendedJsonRpcBatchProvider extend
110
109
  }
111
110
  });
112
111
  }, (error) => {
113
- const event = {
112
+ this._eventEmitter.emitLazy('rpc', () => ({
114
113
  action: 'provider:response-batched:error',
115
114
  error: error,
116
115
  request: properties.deepCopy(batchRequest),
117
116
  provider: this,
118
117
  domain: this._domain,
119
- };
120
- this._eventEmitter.emit('rpc', event);
118
+ }));
121
119
  batch.forEach((inflightRequest) => {
122
120
  inflightRequest.reject(error);
123
121
  });
124
122
  })
125
123
  .catch((error) => {
126
124
  // catch errors happening in the 'then' callback
127
- const event = {
125
+ this._eventEmitter.emitLazy('rpc', () => ({
128
126
  action: 'provider:response-batched:error',
129
127
  error: error,
130
128
  request: properties.deepCopy(batchRequest),
131
129
  provider: this,
132
130
  domain: this._domain,
133
- };
134
- this._eventEmitter.emit('rpc', event);
131
+ }));
135
132
  batch.forEach((inflightRequest) => {
136
133
  inflightRequest.reject(error);
137
134
  });
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { BaseProvider, Formatter, TransactionRequest } from '@ethersproject/providers';
3
2
  import { CallOverrides as CallOverridesSource } from '@ethersproject/contracts';
4
3
  import { SimpleFallbackProviderConfig } from '../interfaces/simple-fallback-provider-config';
@@ -12,6 +11,7 @@ import { EventType, Listener } from '@ethersproject/abstract-provider';
12
11
  import { FeeHistory } from '../ethers/fee-history';
13
12
  import { WaitForTransactionOptions, WaitForTransactionResult } from '../interfaces/wait-for-transaction';
14
13
  import { TraceConfig, TraceResult } from '../interfaces/debug-traces';
14
+ import { LazyEventEmitter } from '../common/lazy-event-emitter';
15
15
  import { FallbackProviderEvents } from '../events';
16
16
  /**
17
17
  * EIP-1898 support
@@ -29,7 +29,7 @@ declare module '@ethersproject/providers' {
29
29
  blockTag?: BlockTag;
30
30
  }
31
31
  }
32
- export interface SimpleFallbackJsonRpcBatchProviderEventEmitter extends NodeJS.EventEmitter {
32
+ export interface SimpleFallbackJsonRpcBatchProviderEventEmitter extends LazyEventEmitter {
33
33
  on(eventName: 'rpc', listener: (event: FallbackProviderEvents) => void): this;
34
34
  once(eventName: 'rpc', listener: (event: FallbackProviderEvents) => void): this;
35
35
  addListener(eventName: 'rpc', listener: (event: FallbackProviderEvents) => void): this;
@@ -44,6 +44,7 @@ export declare class SimpleFallbackJsonRpcBatchProvider extends BaseProvider {
44
44
  protected lastPerformError: Error | null | unknown;
45
45
  protected lastError: Error | null | unknown;
46
46
  protected _eventEmitter: SimpleFallbackJsonRpcBatchProviderEventEmitter;
47
+ protected _childRpcListenersAttached: boolean;
47
48
  constructor(config: SimpleFallbackProviderConfig, logger: LoggerService);
48
49
  static _formatter: Formatter | null;
49
50
  static getFormatter(): Formatter;
@@ -63,6 +64,16 @@ export declare class SimpleFallbackJsonRpcBatchProvider extends BaseProvider {
63
64
  protected networksEqual(networkA: Network, networkB: Network): boolean;
64
65
  get activeProviderIndex(): number;
65
66
  get eventEmitter(): SimpleFallbackJsonRpcBatchProviderEventEmitter;
67
+ /**
68
+ * Sets up lazy subscription to child provider events.
69
+ * Only attaches listeners to child providers when someone subscribes to the parent eventEmitter.
70
+ * This avoids unnecessary event processing when no one is listening.
71
+ */
72
+ protected _setupLazyChildListeners(): void;
73
+ /**
74
+ * Attaches listeners to all child providers to re-emit their events on the parent eventEmitter.
75
+ */
76
+ protected _attachChildRpcListeners(): void;
66
77
  /**
67
78
  * Waits for transaction confirmation with fallback provider support.
68
79
  *
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var tslib = require('tslib');
6
4
  var providers = require('@ethersproject/providers');
7
5
  var extendedJsonRpcBatchProvider = require('./extended-json-rpc-batch-provider.js');
@@ -17,7 +15,7 @@ var requestTimeout_error = require('../error/request-timeout.error.js');
17
15
  var transactionWaitTimeout_error = require('../error/transaction-wait-timeout.error.js');
18
16
  var feeHistory = require('../ethers/fee-history.js');
19
17
  var debugTraceBlockByHash = require('../ethers/debug-trace-block-by-hash.js');
20
- var events = require('events');
18
+ var lazyEventEmitter = require('../common/lazy-event-emitter.js');
21
19
 
22
20
  exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchProvider extends providers.BaseProvider {
23
21
  constructor(config, logger) {
@@ -28,7 +26,9 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
28
26
  // it is crucial not to mix these two errors
29
27
  this.lastPerformError = null; // last error for 'perform' operations, is batch-oriented
30
28
  this.lastError = null; // last error for whole provider
31
- this._eventEmitter = new events.EventEmitter();
29
+ this._childRpcListenersAttached = false;
30
+ this._eventEmitter = new lazyEventEmitter.LazyEventEmitter();
31
+ this._setupLazyChildListeners();
32
32
  this.config = Object.assign({ maxRetries: 3, minBackoffMs: 500, maxBackoffMs: 5000, logRetries: true, resetIntervalMs: 10000, maxTimeWithoutNewBlocksMs: 60000 }, config);
33
33
  this.logger = logger;
34
34
  const conns = config.urls.filter((url) => {
@@ -46,10 +46,6 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
46
46
  this.fallbackProviders = conns.map((conn, index) => {
47
47
  var _a;
48
48
  const provider = new extendedJsonRpcBatchProvider.ExtendedJsonRpcBatchProvider(conn, undefined, config.requestPolicy, (_a = config.fetchMiddlewares) !== null && _a !== void 0 ? _a : []);
49
- // re-emitting events from fallback-providers
50
- provider.eventEmitter.on('rpc', (event) => {
51
- this._eventEmitter.emit('rpc', event);
52
- });
53
49
  return {
54
50
  network: null,
55
51
  provider,
@@ -183,15 +179,14 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
183
179
  // without it, the error will not be caught in current try-catch scope
184
180
  const result = await retry(() => {
185
181
  const provider = this.provider;
186
- const event = {
182
+ this._eventEmitter.emitLazy('rpc', () => ({
187
183
  action: 'fallback-provider:request',
188
184
  provider: this,
189
185
  activeFallbackProviderIndex: this.activeFallbackProviderIndex,
190
186
  fallbackProvidersCount: this.fallbackProviders.length,
191
187
  domain: provider.provider.domain,
192
188
  retryAttempt: performRetryAttempt,
193
- };
194
- this._eventEmitter.emit('rpc', event);
189
+ }));
195
190
  performRetryAttempt++;
196
191
  const performPromise = provider.provider.perform(method, params);
197
192
  // Apply timeout if configured
@@ -208,12 +203,11 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
208
203
  this.lastError = e;
209
204
  // checking that error should not be retried on another provider
210
205
  if (this.isNonRetryableError(e)) {
211
- const event = {
206
+ this._eventEmitter.emitLazy('rpc', () => ({
212
207
  action: 'fallback-provider:request:non-retryable-error',
213
208
  provider: this,
214
209
  error: e,
215
- };
216
- this._eventEmitter.emit('rpc', event);
210
+ }));
217
211
  // Log context (label + provider index) synchronously before error object
218
212
  // to ensure proper ordering in async logging systems
219
213
  this.logger.error(this.formatLog(`${method} non-retryable error occurred`, this.activeFallbackProviderIndex));
@@ -243,12 +237,11 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
243
237
  }
244
238
  const allProvidersFailedError = new allProvidersFailed_error.AllProvidersFailedError(`All attempts to do ETH1 RPC request failed for ${method}`);
245
239
  allProvidersFailedError.cause = this.lastError;
246
- const event = {
240
+ this._eventEmitter.emitLazy('rpc', () => ({
247
241
  action: 'fallback-provider:request:failed:all',
248
242
  provider: this,
249
243
  error: allProvidersFailedError,
250
- };
251
- this._eventEmitter.emit('rpc', event);
244
+ }));
252
245
  throw allProvidersFailedError;
253
246
  }
254
247
  async detectNetwork() {
@@ -331,6 +324,29 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
331
324
  get eventEmitter() {
332
325
  return this._eventEmitter;
333
326
  }
327
+ /**
328
+ * Sets up lazy subscription to child provider events.
329
+ * Only attaches listeners to child providers when someone subscribes to the parent eventEmitter.
330
+ * This avoids unnecessary event processing when no one is listening.
331
+ */
332
+ _setupLazyChildListeners() {
333
+ this._eventEmitter.on('newListener', (eventName) => {
334
+ if (eventName === 'rpc' && !this._childRpcListenersAttached) {
335
+ this._childRpcListenersAttached = true;
336
+ this._attachChildRpcListeners();
337
+ }
338
+ });
339
+ }
340
+ /**
341
+ * Attaches listeners to all child providers to re-emit their events on the parent eventEmitter.
342
+ */
343
+ _attachChildRpcListeners() {
344
+ for (const fallbackProvider of this.fallbackProviders) {
345
+ fallbackProvider.provider.eventEmitter.on('rpc', (event) => {
346
+ this._eventEmitter.emit('rpc', event);
347
+ });
348
+ }
349
+ }
334
350
  /**
335
351
  * Waits for transaction confirmation with fallback provider support.
336
352
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lido-nestjs/execution",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "MIT",