ethers-rpc-pool 1.1.0 → 1.1.1
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/README.md +107 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,31 @@ Designed for production backends and dApps that need:
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- [Why ethers-rpc-pool](#why-ethers-rpc-pool)
|
|
21
|
+
- [Features](#features)
|
|
22
|
+
- [Requirements](#requirements)
|
|
23
|
+
- [Installation](#installation)
|
|
24
|
+
- [Quick Start](#quick-start)
|
|
25
|
+
- [Configuration](#configuration)
|
|
26
|
+
- - [Interfaces](#interfaces)
|
|
27
|
+
- - [RPCPoolProvider Options](#rpcpoolprovider-options)
|
|
28
|
+
- - [JsonRpcProvider Options](#jsonrpcprovider-options)
|
|
29
|
+
- [How It Works](#how-it-works)
|
|
30
|
+
- - [Routing](#1-routing)
|
|
31
|
+
- - [Concurrency Control](#2-concurrency-control)
|
|
32
|
+
- - [Rate Limiting](#3-rate-limiting)
|
|
33
|
+
- - [Retry Strategy](#4-retry-strategy)
|
|
34
|
+
- [Instrumentation & Metrics](#instrumentation--metrics)
|
|
35
|
+
- [Production Considerations](#production-considerations)
|
|
36
|
+
- - [Recommended Settings](#recommended-settings)
|
|
37
|
+
- - [Known Limitations](#known-limitations)
|
|
38
|
+
- [When To Use](#when-to-use)
|
|
39
|
+
- [Example Architecture](#example-architecture)
|
|
40
|
+
- [Roadmap](#roadmap)
|
|
41
|
+
- [License](#license)
|
|
42
|
+
|
|
18
43
|
## Why ethers-rpc-pool?
|
|
19
44
|
|
|
20
45
|
Most production apps rely on a single RPC provider. This creates:
|
|
@@ -68,18 +93,17 @@ import { RPCPoolProvider } from 'ethers-rpc-pool';
|
|
|
68
93
|
const poolProvider = new RPCPoolProvider({
|
|
69
94
|
chainId: 1,
|
|
70
95
|
rpc: [
|
|
71
|
-
{ url: '
|
|
72
|
-
{ url: '
|
|
73
|
-
{ url: '
|
|
74
|
-
{ url: '
|
|
75
|
-
{ url: '
|
|
96
|
+
{ url: 'https://eth.drpc.org' },
|
|
97
|
+
{ url: 'https://eth1.lava.build' },
|
|
98
|
+
{ url: 'https://rpc.mevblocker.io' },
|
|
99
|
+
{ url: 'https://eth.blockrazor.xyz' },
|
|
100
|
+
{ url: 'https://public-eth.nownodes.io' },
|
|
76
101
|
],
|
|
77
102
|
defaultRpcOptions: { inFlight: 1, timeout: 3000, rps: 2, rpsBurst: 5 },
|
|
78
|
-
retry: { attempts:
|
|
103
|
+
retry: { attempts: 3 },
|
|
79
104
|
});
|
|
80
105
|
|
|
81
106
|
// Use it like a regular `JsonRpcProvider`:
|
|
82
|
-
|
|
83
107
|
const blockNumber = await poolProvider.getBlockNumber();
|
|
84
108
|
const balance = await poolProvider.getBalance('0x...');
|
|
85
109
|
```
|
|
@@ -88,25 +112,37 @@ const balance = await poolProvider.getBalance('0x...');
|
|
|
88
112
|
|
|
89
113
|
## Configuration
|
|
90
114
|
|
|
91
|
-
###
|
|
115
|
+
### Interfaces
|
|
92
116
|
|
|
93
117
|
```ts
|
|
94
|
-
interface
|
|
118
|
+
interface RPCParameters {
|
|
119
|
+
inFlight?: number;
|
|
120
|
+
timeout?: number;
|
|
121
|
+
rps?: number;
|
|
122
|
+
rpsBurst?: number;
|
|
123
|
+
|
|
124
|
+
// Optional instrumentation hook for provider-level events
|
|
125
|
+
stats?: Stats;
|
|
126
|
+
onEvent?: (e: RpcEvent) => void;
|
|
127
|
+
providerId: string;
|
|
128
|
+
|
|
129
|
+
// Optional JsonRpcProvider options for compatibility
|
|
130
|
+
// https://docs.ethers.org/v6/api/providers/jsonrpc/#JsonRpcApiProviderOptions
|
|
131
|
+
batchStallTime?: number;
|
|
132
|
+
batchMaxSize?: number;
|
|
133
|
+
batchMaxCount?: number;
|
|
134
|
+
staticNetwork?: null | boolean | Network;
|
|
135
|
+
polling?: boolean;
|
|
136
|
+
cacheTimeout?: number;
|
|
137
|
+
pollingInterval?: number;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
interface PoolProviderParameters {
|
|
95
143
|
network: number;
|
|
96
|
-
rpc:
|
|
97
|
-
|
|
98
|
-
timeout?: number;
|
|
99
|
-
rps?: number;
|
|
100
|
-
rpsBurst?: number;
|
|
101
|
-
}[];
|
|
102
|
-
defaultRpcOptions?: {
|
|
103
|
-
timeout?: number;
|
|
104
|
-
rps?: number;
|
|
105
|
-
rpsBurst?: number;
|
|
106
|
-
};
|
|
107
|
-
perUrl: {
|
|
108
|
-
inFlight: number;
|
|
109
|
-
};
|
|
144
|
+
rpc: RpcProviderOptions[];
|
|
145
|
+
defaultRpcOptions?: RpcProviderOptions;
|
|
110
146
|
retry: {
|
|
111
147
|
attempts: number;
|
|
112
148
|
};
|
|
@@ -116,18 +152,25 @@ interface RPCPoolProviderParams {
|
|
|
116
152
|
}
|
|
117
153
|
```
|
|
118
154
|
|
|
119
|
-
### Options
|
|
155
|
+
### RPCPoolProvider Options
|
|
156
|
+
|
|
157
|
+
| Option | Description |
|
|
158
|
+
| ------------------- | ----------------------------------------- |
|
|
159
|
+
| `network` | Target chain ID |
|
|
160
|
+
| `rpc` | List of RPC endpoints |
|
|
161
|
+
| `retry.attempts` | Maximum number of unique endpoints to try |
|
|
162
|
+
| `defaultRpcOptions` | Default options for all RPC endpoints |
|
|
163
|
+
| `hooks.onEvent` | Optional instrumentation hook |
|
|
164
|
+
|
|
165
|
+
### JsonRpcProvider Options
|
|
120
166
|
|
|
121
|
-
| Option
|
|
122
|
-
|
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
|
|
|
128
|
-
| `defaultRpcOptions.rpsBurst` | Maximum burst capacity for the rate limiter. Allows short spikes above the sustained rate by accumulating tokens during idle periods. |
|
|
129
|
-
| `retry.attempts` | Maximum number of unique endpoints to try |
|
|
130
|
-
| `hooks.onEvent` | Optional instrumentation hook |
|
|
167
|
+
| Option | Description |
|
|
168
|
+
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
169
|
+
| `inFlight` | Max concurrent requests per endpoint |
|
|
170
|
+
| `timeout` | Timeout in ms for each request to this URL, default 10s |
|
|
171
|
+
| `rps` | Maximum number of requests per second allowed for a single RPC endpoint. Enforced using a token bucket rate limiter. |
|
|
172
|
+
| `rpsBurst` | Maximum burst capacity for the rate limiter. Allows short spikes above the sustained rate by accumulating tokens during idle periods. |
|
|
173
|
+
| ... | Also allows customization of [ethers.JsonRpcApiProviderOptions](https://docs.ethers.org/v6/api/providers/jsonrpc/#JsonRpcApiProviderOptions) |
|
|
131
174
|
|
|
132
175
|
---
|
|
133
176
|
|
|
@@ -141,7 +184,7 @@ Requests are routed through an internal `Router`, which selects an available end
|
|
|
141
184
|
|
|
142
185
|
Each endpoint has its own semaphore limiter:
|
|
143
186
|
|
|
144
|
-
```
|
|
187
|
+
```
|
|
145
188
|
inFlight: number;
|
|
146
189
|
```
|
|
147
190
|
|
|
@@ -151,7 +194,34 @@ This prevents:
|
|
|
151
194
|
- Triggering provider-side throttling
|
|
152
195
|
- Self-induced retry storms
|
|
153
196
|
|
|
154
|
-
### 3.
|
|
197
|
+
### 3. Rate Limiting
|
|
198
|
+
|
|
199
|
+
Each RPC endpoint uses a token bucket rate limiter to control request throughput.
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
rps: number;
|
|
203
|
+
rpsBurst: number;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Where:
|
|
207
|
+
|
|
208
|
+
- `rps` defines the sustained request rate
|
|
209
|
+
- `rpsBurst` defines how many requests may temporarily exceed that rate (**maximum burst capacity**)
|
|
210
|
+
|
|
211
|
+
This helps:
|
|
212
|
+
|
|
213
|
+
- Prevent 429 rate limit errors
|
|
214
|
+
- Smooth traffic spikes
|
|
215
|
+
- Protect RPC providers
|
|
216
|
+
- Improve overall system stability
|
|
217
|
+
|
|
218
|
+
Unused capacity accumulates as tokens and may be consumed during short traffic bursts.
|
|
219
|
+
|
|
220
|
+
### 4. Retry Strategy
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
retry.attempts: number
|
|
224
|
+
```
|
|
155
225
|
|
|
156
226
|
If a retryable error occurs:
|
|
157
227
|
|
|
@@ -251,13 +321,12 @@ Useful for:
|
|
|
251
321
|
|
|
252
322
|
- `inFlight`: 1–2 depending on rpc provider limits
|
|
253
323
|
- `retry.attempts`: 2–3
|
|
254
|
-
- Use at least
|
|
324
|
+
- Use at least 3–5 independent RPC providers
|
|
255
325
|
|
|
256
326
|
### Known Limitations
|
|
257
327
|
|
|
258
328
|
- Basic circuit breaker/cooldown
|
|
259
329
|
- No sticky session/blockTag consistency yet
|
|
260
|
-
- No built-in JSON-RPC batching
|
|
261
330
|
- Archive/debug/trace methods depend on underlying RPC support
|
|
262
331
|
|
|
263
332
|
---
|
|
@@ -301,7 +370,6 @@ Not intended for:
|
|
|
301
370
|
- Circuit breaker + health scoring
|
|
302
371
|
- Sticky session / blockTag consistency
|
|
303
372
|
- Adaptive latency-based routing
|
|
304
|
-
- JSON-RPC batch support
|
|
305
373
|
- Singleflight request deduplication
|
|
306
374
|
|
|
307
375
|
---
|