0
# Batch Request Processing
1
2
The Web3 batch request system enables efficient grouping of multiple JSON-RPC requests into single network calls, reducing latency and improving performance for applications that need to make multiple blockchain queries simultaneously.
3
4
## Capabilities
5
6
### Web3BatchRequest Class
7
8
Main class for creating and executing batched JSON-RPC requests with promise-based result handling.
9
10
```typescript { .api }
11
/**
12
* Manages batched JSON-RPC requests for improved efficiency and reduced network overhead
13
*/
14
class Web3BatchRequest {
15
constructor(requestManager: Web3RequestManager);
16
17
// Properties
18
readonly requests: JsonRpcRequest[];
19
20
// Batch management
21
add<ResponseType = unknown>(
22
request: JsonRpcOptionalRequest<unknown>
23
): Web3DeferredPromise<ResponseType>;
24
25
execute(options?: {timeout?: number}): Promise<JsonRpcBatchResponse<unknown, unknown>>;
26
}
27
```
28
29
**Usage Examples:**
30
31
```typescript
32
import { Web3BatchRequest, Web3RequestManager } from "web3-core";
33
import { EthExecutionAPI } from "web3-types";
34
35
// Create request manager and batch request
36
const requestManager = new Web3RequestManager<EthExecutionAPI>(
37
"https://eth-mainnet.g.alchemy.com/v2/your-api-key"
38
);
39
40
const batch = new Web3BatchRequest(requestManager);
41
42
// Add requests to batch and get promise handles
43
const blockNumberPromise = batch.add<string>({
44
method: "eth_blockNumber",
45
params: []
46
});
47
48
const gasPricePromise = batch.add<string>({
49
method: "eth_gasPrice",
50
params: []
51
});
52
53
const balancePromise = batch.add<string>({
54
method: "eth_getBalance",
55
params: ["0x742d35Cc6634C0532925a3b8D0d3", "latest"]
56
});
57
58
// Execute batch - all requests sent in one network call
59
const batchResults = await batch.execute();
60
61
// Access individual results through promises
62
const blockNumber = await blockNumberPromise;
63
const gasPrice = await gasPricePromise;
64
const balance = await balancePromise;
65
66
console.log("Block number:", parseInt(blockNumber, 16));
67
console.log("Gas price:", parseInt(gasPrice, 16), "wei");
68
console.log("Balance:", parseInt(balance, 16), "wei");
69
```
70
71
### Batch Request Building
72
73
Methods for constructing batched requests with individual promise handles for results.
74
75
```typescript { .api }
76
/**
77
* Add a JSON-RPC request to the batch
78
* @template ResponseType - Expected response data type
79
* @param request - JSON-RPC request object (without id and jsonrpc fields)
80
* @returns Promise that resolves to the specific request's response
81
*/
82
add<ResponseType = unknown>(
83
request: JsonRpcOptionalRequest<unknown>
84
): Web3DeferredPromise<ResponseType>;
85
86
/**
87
* Access the array of queued requests
88
*/
89
readonly requests: JsonRpcRequest[];
90
```
91
92
**Usage Examples:**
93
94
```typescript
95
const batch = new Web3BatchRequest(requestManager);
96
97
// Add various types of requests
98
const calls = [
99
batch.add<string>({ method: "eth_blockNumber", params: [] }),
100
batch.add<string>({ method: "eth_gasPrice", params: [] }),
101
batch.add<Block>({
102
method: "eth_getBlockByNumber",
103
params: ["latest", true]
104
}),
105
batch.add<string>({
106
method: "eth_getBalance",
107
params: ["0x742d35Cc6634C0532925a3b8D0d3", "latest"]
108
}),
109
batch.add<Transaction>({
110
method: "eth_getTransactionByHash",
111
params: ["0x1234567890abcdef..."]
112
})
113
];
114
115
// Inspect batch before execution
116
console.log("Batch contains", batch.requests.length, "requests");
117
batch.requests.forEach((req, index) => {
118
console.log(`Request ${index + 1}: ${req.method}`);
119
});
120
121
// Execute and handle results
122
await batch.execute();
123
124
// Process results individually
125
const [blockNumber, gasPrice, latestBlock, balance, transaction] = await Promise.all(calls);
126
127
console.log("Results:", {
128
blockNumber: parseInt(blockNumber, 16),
129
gasPrice: parseInt(gasPrice, 16),
130
blockHash: latestBlock.hash,
131
balance: parseInt(balance, 16),
132
txValue: transaction.value
133
});
134
```
135
136
### Batch Execution
137
138
Execute batched requests with configurable timeout and comprehensive error handling.
139
140
```typescript { .api }
141
/**
142
* Execute all queued requests in a single batch call
143
* @param options - Execution options
144
* @param options.timeout - Request timeout in milliseconds
145
* @returns Promise resolving to batch response with all results
146
*/
147
execute(options?: {timeout?: number}): Promise<JsonRpcBatchResponse<unknown, unknown>>;
148
149
/**
150
* Default batch request timeout constant
151
*/
152
const DEFAULT_BATCH_REQUEST_TIMEOUT: 1000;
153
```
154
155
**Usage Examples:**
156
157
```typescript
158
// Execute with default timeout
159
const batchResponse = await batch.execute();
160
161
// Execute with custom timeout (30 seconds)
162
const longBatchResponse = await batch.execute({ timeout: 30000 });
163
164
// Handle batch response
165
batchResponse.forEach((response, index) => {
166
if ('result' in response) {
167
console.log(`Request ${index + 1} succeeded:`, response.result);
168
} else if ('error' in response) {
169
console.error(`Request ${index + 1} failed:`, response.error);
170
}
171
});
172
173
// Error handling for batch execution
174
try {
175
await batch.execute({ timeout: 5000 });
176
} catch (error) {
177
if (error.name === 'TimeoutError') {
178
console.error("Batch request timed out after 5 seconds");
179
} else {
180
console.error("Batch execution failed:", error.message);
181
}
182
}
183
```
184
185
### Advanced Batch Patterns
186
187
Common patterns and best practices for efficient batch request usage.
188
189
```typescript { .api }
190
/**
191
* Web3DeferredPromise type for individual batch request results
192
* @template T - Response type
193
*/
194
type Web3DeferredPromise<T> = Promise<T>;
195
196
/**
197
* JSON-RPC batch response type
198
*/
199
type JsonRpcBatchResponse<Result = unknown, Error = unknown> = Array<
200
JsonRpcResponse<Result> | JsonRpcError<Error>
201
>;
202
203
/**
204
* Optional request type (id and jsonrpc fields added automatically)
205
*/
206
type JsonRpcOptionalRequest<T> = {
207
method: string;
208
params?: T;
209
};
210
```
211
212
**Usage Examples:**
213
214
```typescript
215
// Pattern: Batch multiple balance checks
216
async function getBatchedBalances(addresses: string[]): Promise<{[address: string]: string}> {
217
const batch = new Web3BatchRequest(requestManager);
218
219
const balancePromises = addresses.map(address => ({
220
address,
221
promise: batch.add<string>({
222
method: "eth_getBalance",
223
params: [address, "latest"]
224
})
225
}));
226
227
await batch.execute();
228
229
const balances: {[address: string]: string} = {};
230
for (const { address, promise } of balancePromises) {
231
try {
232
balances[address] = await promise;
233
} catch (error) {
234
console.error(`Failed to get balance for ${address}:`, error);
235
balances[address] = "0x0";
236
}
237
}
238
239
return balances;
240
}
241
242
// Pattern: Batch block range queries
243
async function getBlockRange(startBlock: number, endBlock: number): Promise<Block[]> {
244
const batch = new Web3BatchRequest(requestManager);
245
246
const blockPromises = [];
247
for (let i = startBlock; i <= endBlock; i++) {
248
blockPromises.push({
249
blockNumber: i,
250
promise: batch.add<Block>({
251
method: "eth_getBlockByNumber",
252
params: [`0x${i.toString(16)}`, false]
253
})
254
});
255
}
256
257
await batch.execute({ timeout: 30000 }); // Longer timeout for many blocks
258
259
const blocks: Block[] = [];
260
for (const { blockNumber, promise } of blockPromises) {
261
try {
262
const block = await promise;
263
blocks.push(block);
264
} catch (error) {
265
console.error(`Failed to get block ${blockNumber}:`, error);
266
}
267
}
268
269
return blocks.sort((a, b) => parseInt(a.number, 16) - parseInt(b.number, 16));
270
}
271
272
// Pattern: Mixed request types with error handling
273
async function getDashboardData(userAddress: string) {
274
const batch = new Web3BatchRequest(requestManager);
275
276
const promises = {
277
blockNumber: batch.add<string>({ method: "eth_blockNumber", params: [] }),
278
gasPrice: batch.add<string>({ method: "eth_gasPrice", params: [] }),
279
balance: batch.add<string>({
280
method: "eth_getBalance",
281
params: [userAddress, "latest"]
282
}),
283
transactionCount: batch.add<string>({
284
method: "eth_getTransactionCount",
285
params: [userAddress, "latest"]
286
}),
287
chainId: batch.add<string>({ method: "eth_chainId", params: [] })
288
};
289
290
await batch.execute();
291
292
try {
293
const [blockNumber, gasPrice, balance, txCount, chainId] = await Promise.all([
294
promises.blockNumber,
295
promises.gasPrice,
296
promises.balance,
297
promises.transactionCount,
298
promises.chainId
299
]);
300
301
return {
302
currentBlock: parseInt(blockNumber, 16),
303
gasPrice: parseInt(gasPrice, 16),
304
userBalance: balance,
305
transactionCount: parseInt(txCount, 16),
306
chainId: parseInt(chainId, 16)
307
};
308
} catch (error) {
309
console.error("Some dashboard data requests failed:", error);
310
throw error;
311
}
312
}
313
314
// Usage
315
const addresses = ["0x742d35Cc6634C0532925a3b8D0d3", "0x8ba1f109551bD432803012645Hac136c"];
316
const balances = await getBatchedBalances(addresses);
317
318
const blocks = await getBlockRange(18000000, 18000010);
319
320
const dashboardData = await getDashboardData("0x742d35Cc6634C0532925a3b8D0d3");
321
```
322
323
### Performance Benefits
324
325
Batch processing provides significant performance improvements over individual requests:
326
327
- **Reduced Network Latency**: Multiple requests sent in one HTTP call
328
- **Lower Connection Overhead**: Single TCP connection handles multiple requests
329
- **Server Efficiency**: Blockchain nodes can optimize batch processing
330
- **Rate Limit Optimization**: Batch counts as single request for rate limiting
331
- **Error Isolation**: Individual request failures don't affect other requests in batch
332
333
**Performance Comparison Example:**
334
335
```typescript
336
// ❌ Inefficient: Individual requests
337
async function getDataIndividually() {
338
const start = Date.now();
339
340
const blockNumber = await requestManager.send({ method: "eth_blockNumber", params: [] });
341
const gasPrice = await requestManager.send({ method: "eth_gasPrice", params: [] });
342
const balance = await requestManager.send({
343
method: "eth_getBalance",
344
params: ["0x742d35Cc6634C0532925a3b8D0d3", "latest"]
345
});
346
347
const end = Date.now();
348
console.log(`Individual requests took: ${end - start}ms`);
349
350
return { blockNumber, gasPrice, balance };
351
}
352
353
// ✅ Efficient: Batch requests
354
async function getDataBatched() {
355
const start = Date.now();
356
357
const batch = new Web3BatchRequest(requestManager);
358
const blockNumberPromise = batch.add({ method: "eth_blockNumber", params: [] });
359
const gasPricePromise = batch.add({ method: "eth_gasPrice", params: [] });
360
const balancePromise = batch.add({
361
method: "eth_getBalance",
362
params: ["0x742d35Cc6634C0532925a3b8D0d3", "latest"]
363
});
364
365
await batch.execute();
366
367
const [blockNumber, gasPrice, balance] = await Promise.all([
368
blockNumberPromise,
369
gasPricePromise,
370
balancePromise
371
]);
372
373
const end = Date.now();
374
console.log(`Batch requests took: ${end - start}ms`);
375
376
return { blockNumber, gasPrice, balance };
377
}
378
379
// Typical results: Batch is 60-80% faster than individual requests
380
```