@lido-nestjs/execution 1.17.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.
- package/dist/batch-provider.module.js +0 -2
- package/dist/common/errors.js +0 -2
- package/dist/common/lazy-event-emitter.d.ts +9 -0
- package/dist/common/lazy-event-emitter.js +18 -0
- package/dist/common/networks.js +0 -2
- package/dist/common/promise-limit.js +2 -1
- package/dist/common/queue.js +0 -2
- package/dist/common/retrier.js +0 -2
- package/dist/common/sleep.js +0 -2
- package/dist/constants/constants.js +0 -2
- package/dist/error/all-providers-failed.error.js +0 -2
- package/dist/error/codes/error-codes.js +0 -2
- package/dist/error/fetch.error.js +0 -2
- package/dist/error/no-new-blocks-while-polling.error.js +0 -2
- package/dist/error/request-timeout.error.js +0 -2
- package/dist/error/transaction-wait-timeout.error.js +0 -2
- package/dist/ethers/debug-trace-block-by-hash.js +0 -2
- package/dist/ethers/fee-history.js +0 -2
- package/dist/ethers/format-block-number.js +0 -2
- package/dist/ethers/formatter-with-eip1898.js +0 -2
- package/dist/events/index.d.ts +1 -2
- package/dist/fallback-provider.module.js +0 -2
- package/dist/index.js +4 -6
- package/dist/provider/extended-json-rpc-batch-provider.d.ts +2 -1
- package/dist/provider/extended-json-rpc-batch-provider.js +16 -19
- package/dist/provider/simple-fallback-json-rpc-batch-provider.d.ts +13 -2
- package/dist/provider/simple-fallback-json-rpc-batch-provider.js +57 -29
- package/package.json +1 -1
package/dist/common/errors.js
CHANGED
|
@@ -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;
|
package/dist/common/networks.js
CHANGED
|
@@ -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
|
|
66
|
+
exports.default = pLimit;
|
package/dist/common/queue.js
CHANGED
package/dist/common/retrier.js
CHANGED
|
@@ -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) => {
|
package/dist/common/sleep.js
CHANGED
package/dist/events/index.d.ts
CHANGED
|
@@ -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
|
|
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
|
};
|
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,
|
|
17
|
+
Object.defineProperty(exports, "ExtendedJsonRpcBatchProvider", {
|
|
20
18
|
enumerable: true,
|
|
21
19
|
get: function () { return extendedJsonRpcBatchProvider.ExtendedJsonRpcBatchProvider; }
|
|
22
20
|
});
|
|
23
|
-
Object.defineProperty(exports,
|
|
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,
|
|
26
|
+
Object.defineProperty(exports, "FallbackProviderModule", {
|
|
29
27
|
enumerable: true,
|
|
30
28
|
get: function () { return fallbackProvider_module.FallbackProviderModule; }
|
|
31
29
|
});
|
|
32
|
-
Object.defineProperty(exports,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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,
|
|
@@ -166,8 +162,10 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
166
162
|
]);
|
|
167
163
|
}
|
|
168
164
|
async perform(method, params) {
|
|
165
|
+
var _a, _b;
|
|
169
166
|
const retry = retrier.retrier(this.logger, this.config.maxRetries, this.config.minBackoffMs, this.config.maxBackoffMs, this.config.logRetries, (e) => this.isNonRetryableError(e));
|
|
170
167
|
let attempt = 0;
|
|
168
|
+
(_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, this.formatLog(`RPC call: ${method}`));
|
|
171
169
|
// will perform maximum `this.config.maxRetries` retries for fetching data with single provider
|
|
172
170
|
// after failure will switch to next provider
|
|
173
171
|
// maximum number of switching is limited to total fallback provider count
|
|
@@ -176,20 +174,19 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
176
174
|
let performRetryAttempt = 0;
|
|
177
175
|
attempt++;
|
|
178
176
|
// Log which provider we're attempting to use
|
|
179
|
-
this.logger.log(this.formatLog(`Attempting
|
|
177
|
+
this.logger.log(this.formatLog(`Attempting ${method} (attempt ${attempt}/${this.fallbackProviders.length})`, this.activeFallbackProviderIndex));
|
|
180
178
|
// awaiting is extremely important here
|
|
181
179
|
// without it, the error will not be caught in current try-catch scope
|
|
182
180
|
const result = await retry(() => {
|
|
183
181
|
const provider = this.provider;
|
|
184
|
-
|
|
182
|
+
this._eventEmitter.emitLazy('rpc', () => ({
|
|
185
183
|
action: 'fallback-provider:request',
|
|
186
184
|
provider: this,
|
|
187
185
|
activeFallbackProviderIndex: this.activeFallbackProviderIndex,
|
|
188
186
|
fallbackProvidersCount: this.fallbackProviders.length,
|
|
189
187
|
domain: provider.provider.domain,
|
|
190
188
|
retryAttempt: performRetryAttempt,
|
|
191
|
-
};
|
|
192
|
-
this._eventEmitter.emit('rpc', event);
|
|
189
|
+
}));
|
|
193
190
|
performRetryAttempt++;
|
|
194
191
|
const performPromise = provider.provider.perform(method, params);
|
|
195
192
|
// Apply timeout if configured
|
|
@@ -199,33 +196,32 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
199
196
|
return performPromise;
|
|
200
197
|
});
|
|
201
198
|
// Log successful request
|
|
202
|
-
this.logger.log(this.formatLog(
|
|
199
|
+
this.logger.log(this.formatLog(`${method} successful after ${performRetryAttempt} retry attempt(s)`, this.activeFallbackProviderIndex));
|
|
203
200
|
return result;
|
|
204
201
|
}
|
|
205
202
|
catch (e) {
|
|
206
203
|
this.lastError = e;
|
|
207
204
|
// checking that error should not be retried on another provider
|
|
208
205
|
if (this.isNonRetryableError(e)) {
|
|
209
|
-
|
|
206
|
+
this._eventEmitter.emitLazy('rpc', () => ({
|
|
210
207
|
action: 'fallback-provider:request:non-retryable-error',
|
|
211
208
|
provider: this,
|
|
212
209
|
error: e,
|
|
213
|
-
};
|
|
214
|
-
this._eventEmitter.emit('rpc', event);
|
|
210
|
+
}));
|
|
215
211
|
// Log context (label + provider index) synchronously before error object
|
|
216
212
|
// to ensure proper ordering in async logging systems
|
|
217
|
-
this.logger.error(this.formatLog(
|
|
213
|
+
this.logger.error(this.formatLog(`${method} non-retryable error occurred`, this.activeFallbackProviderIndex));
|
|
218
214
|
this.logger.error(e);
|
|
219
215
|
throw e;
|
|
220
216
|
}
|
|
221
217
|
// Log context (label + provider index) synchronously before error object
|
|
222
218
|
// to ensure proper ordering in async logging systems
|
|
223
219
|
if (e instanceof requestTimeout_error.RequestTimeoutError) {
|
|
224
|
-
this.logger.error(this.formatLog(
|
|
220
|
+
this.logger.error(this.formatLog(`${method} timeout after ${e.timeoutMs}ms. Will switch to next provider.`, this.activeFallbackProviderIndex));
|
|
225
221
|
this.logger.error(e);
|
|
226
222
|
}
|
|
227
223
|
else {
|
|
228
|
-
this.logger.error(this.formatLog(
|
|
224
|
+
this.logger.error(this.formatLog(`${method} error occurred. Will switch to next provider.`, this.activeFallbackProviderIndex));
|
|
229
225
|
this.logger.error(e);
|
|
230
226
|
}
|
|
231
227
|
// This check is needed to avoid multiple `switchToNextProvider` calls when doing one JSON-RPC batch.
|
|
@@ -239,14 +235,13 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
239
235
|
}
|
|
240
236
|
}
|
|
241
237
|
}
|
|
242
|
-
const allProvidersFailedError = new allProvidersFailed_error.AllProvidersFailedError(
|
|
238
|
+
const allProvidersFailedError = new allProvidersFailed_error.AllProvidersFailedError(`All attempts to do ETH1 RPC request failed for ${method}`);
|
|
243
239
|
allProvidersFailedError.cause = this.lastError;
|
|
244
|
-
|
|
240
|
+
this._eventEmitter.emitLazy('rpc', () => ({
|
|
245
241
|
action: 'fallback-provider:request:failed:all',
|
|
246
242
|
provider: this,
|
|
247
243
|
error: allProvidersFailedError,
|
|
248
|
-
};
|
|
249
|
-
this._eventEmitter.emit('rpc', event);
|
|
244
|
+
}));
|
|
250
245
|
throw allProvidersFailedError;
|
|
251
246
|
}
|
|
252
247
|
async detectNetwork() {
|
|
@@ -329,6 +324,29 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
329
324
|
get eventEmitter() {
|
|
330
325
|
return this._eventEmitter;
|
|
331
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
|
+
}
|
|
332
350
|
/**
|
|
333
351
|
* Waits for transaction confirmation with fallback provider support.
|
|
334
352
|
*
|
|
@@ -351,19 +369,29 @@ exports.SimpleFallbackJsonRpcBatchProvider = class SimpleFallbackJsonRpcBatchPro
|
|
|
351
369
|
try {
|
|
352
370
|
// Uses perform() which handles fallback switching automatically
|
|
353
371
|
const receipt = await this.getTransactionReceipt(txHash);
|
|
354
|
-
if (receipt
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
372
|
+
if (!receipt) {
|
|
373
|
+
// Transaction pending in mempool, not yet included in a block
|
|
374
|
+
lastError = null;
|
|
375
|
+
await sleep.sleep(pollInterval);
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (receipt.confirmations < confirmations) {
|
|
379
|
+
// Transaction mined but waiting for more confirmations
|
|
380
|
+
lastError = null;
|
|
381
|
+
await sleep.sleep(pollInterval);
|
|
382
|
+
continue;
|
|
358
383
|
}
|
|
359
|
-
|
|
384
|
+
// Transaction confirmed with enough confirmations
|
|
385
|
+
const elapsedMs = Date.now() - startTime;
|
|
386
|
+
this.logger.log(this.formatLog(`Transaction ${txHash} confirmed after ${pollCount} polls (${elapsedMs}ms, ${receipt.confirmations} confirmations)`));
|
|
387
|
+
return { receipt, pollCount, elapsedMs };
|
|
360
388
|
}
|
|
361
389
|
catch (error) {
|
|
362
390
|
// All providers failed - log and retry until timeout
|
|
363
391
|
lastError = error;
|
|
364
392
|
this.logger.warn(this.formatLog(`waitForTransactionWithFallback poll #${pollCount} failed for ${txHash}: ${error}`));
|
|
393
|
+
await sleep.sleep(pollInterval);
|
|
365
394
|
}
|
|
366
|
-
await sleep.sleep(pollInterval);
|
|
367
395
|
}
|
|
368
396
|
const elapsedMs = Date.now() - startTime;
|
|
369
397
|
const errorContext = lastError
|