or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-management.mdens-operations.mdethereum-operations.mdindex.mdmiddleware.mdproviders.mdsmart-contracts.mdutilities.mdweb3-client.md

middleware.mddocs/

0

# Middleware

1

2

Request and response processing middleware for customizing Web3 behavior including validation, formatting, signing, filtering, and gas price strategies with composable middleware stack management.

3

4

## Capabilities

5

6

### Base Middleware Classes

7

8

Core middleware infrastructure and base classes.

9

10

```python { .api }

11

class Web3Middleware:

12

def __init__(self, w3: Union[Web3, AsyncWeb3]):

13

"""

14

Initialize middleware with Web3 instance.

15

16

Parameters:

17

- w3: Web3 or AsyncWeb3 instance

18

"""

19

20

def wrap_make_request(self, make_request: MakeRequestFn) -> MakeRequestFn:

21

"""

22

Wrap request function with middleware logic.

23

24

Parameters:

25

- make_request: Original request function

26

27

Returns:

28

Wrapped request function

29

"""

30

31

async def async_wrap_make_request(

32

self,

33

make_request: AsyncMakeRequestFn

34

) -> AsyncMakeRequestFn:

35

"""

36

Wrap async request function with middleware logic.

37

38

Parameters:

39

- make_request: Original async request function

40

41

Returns:

42

Wrapped async request function

43

"""

44

45

Middleware = Callable[[Union[Web3, AsyncWeb3]], Web3Middleware]

46

```

47

48

### Built-in Middleware

49

50

Pre-built middleware for common functionality.

51

52

```python { .api }

53

class AttributeDictMiddleware(Web3Middleware):

54

"""Convert response objects to attribute dictionaries."""

55

56

class BufferedGasEstimateMiddleware(Web3Middleware):

57

"""Buffer gas estimates to avoid repeated calls."""

58

59

class LocalFilterMiddleware(Web3Middleware):

60

"""Handle event filters locally instead of on node."""

61

62

class GasPriceStrategyMiddleware(Web3Middleware):

63

"""Apply gas price strategy to transactions."""

64

65

class ENSNameToAddressMiddleware(Web3Middleware):

66

"""Resolve ENS names to addresses in transactions."""

67

68

class ExtraDataToPOAMiddleware(Web3Middleware):

69

"""Handle Proof of Authority consensus extra data."""

70

71

class PythonicMiddleware(Web3Middleware):

72

"""Convert responses to Pythonic formats."""

73

74

class ValidationMiddleware(Web3Middleware):

75

"""Validate request parameters."""

76

```

77

78

### Middleware Builders

79

80

Factory functions for creating configurable middleware.

81

82

```python { .api }

83

def FormattingMiddlewareBuilder() -> Middleware:

84

"""

85

Create response formatting middleware.

86

87

Returns:

88

Configured formatting middleware

89

"""

90

91

def SignAndSendRawMiddlewareBuilder(

92

private_key_or_account: Union[PrivateKey, LocalAccount]

93

) -> Middleware:

94

"""

95

Create transaction signing middleware.

96

97

Parameters:

98

- private_key_or_account: Private key or account for signing

99

100

Returns:

101

Configured signing middleware

102

"""

103

104

def StalecheckMiddlewareBuilder(

105

allowable_delay: int = 60

106

) -> Middleware:

107

"""

108

Create stale block check middleware.

109

110

Parameters:

111

- allowable_delay: Maximum block age in seconds

112

113

Returns:

114

Configured stalecheck middleware

115

"""

116

```

117

118

### Middleware Management

119

120

Functions for combining and managing middleware stacks.

121

122

```python { .api }

123

def combine_middleware(

124

middleware: Sequence[Middleware],

125

w3: Web3,

126

provider_request_fn: MakeRequestFn

127

) -> Callable[..., RPCResponse]:

128

"""

129

Combine middleware into request processing pipeline.

130

131

Parameters:

132

- middleware: List of middleware functions

133

- w3: Web3 instance

134

- provider_request_fn: Provider's request function

135

136

Returns:

137

Combined request processor

138

"""

139

140

async def async_combine_middleware(

141

middleware: Sequence[Middleware],

142

async_w3: AsyncWeb3,

143

provider_request_fn: AsyncMakeRequestFn

144

) -> Callable[..., Coroutine[Any, Any, RPCResponse]]:

145

"""

146

Combine async middleware into request processing pipeline.

147

148

Parameters:

149

- middleware: List of middleware functions

150

- async_w3: AsyncWeb3 instance

151

- provider_request_fn: Provider's async request function

152

153

Returns:

154

Combined async request processor

155

"""

156

```

157

158

### Middleware Onion

159

160

Middleware stack management interface.

161

162

```python { .api }

163

class MiddlewareOnion:

164

def add(self, middleware: Middleware, name: Optional[str] = None) -> None:

165

"""

166

Add middleware to the top of stack.

167

168

Parameters:

169

- middleware: Middleware function

170

- name: Optional middleware name

171

"""

172

173

def inject(

174

self,

175

middleware: Middleware,

176

name: Optional[str] = None,

177

layer: Optional[int] = None

178

) -> None:

179

"""

180

Inject middleware at specific layer.

181

182

Parameters:

183

- middleware: Middleware function

184

- name: Optional middleware name

185

- layer: Stack position (0 = top)

186

"""

187

188

def remove(self, name: str) -> None:

189

"""

190

Remove middleware by name.

191

192

Parameters:

193

- name: Middleware name to remove

194

"""

195

196

def replace(self, name: str, middleware: Middleware) -> None:

197

"""

198

Replace existing middleware.

199

200

Parameters:

201

- name: Name of middleware to replace

202

- middleware: New middleware function

203

"""

204

205

def clear(self) -> None:

206

"""Remove all middleware from stack."""

207

```

208

209

## Types

210

211

Middleware-related type definitions.

212

213

```python { .api }

214

MakeRequestFn = Callable[[RPCEndpoint, Any], RPCResponse]

215

AsyncMakeRequestFn = Callable[[RPCEndpoint, Any], Coroutine[Any, Any, RPCResponse]]

216

217

class RPCResponse(TypedDict):

218

id: int

219

jsonrpc: str

220

result: Any

221

error: NotRequired[Dict[str, Any]]

222

223

RPCEndpoint = NewType('RPCEndpoint', str)

224

```

225

226

## Usage Examples

227

228

### Basic Middleware Usage

229

230

```python

231

from web3 import Web3

232

from web3.middleware import geth_poa_middleware

233

234

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

235

236

# Add Proof of Authority middleware

237

w3.middleware_onion.inject(geth_poa_middleware, layer=0)

238

239

# Verify middleware is active

240

print(f"Middleware stack: {[name for name, _ in w3.middleware_onion]}")

241

```

242

243

### Custom Middleware

244

245

```python

246

from web3 import Web3

247

from web3.types import RPCEndpoint, RPCResponse

248

249

def request_logging_middleware(make_request, w3):

250

"""Log all RPC requests."""

251

def middleware(method: RPCEndpoint, params):

252

print(f"Making request: {method} with params: {params}")

253

response = make_request(method, params)

254

print(f"Response: {response}")

255

return response

256

return middleware

257

258

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

259

w3.middleware_onion.add(request_logging_middleware, 'logging')

260

261

# All requests will now be logged

262

balance = w3.eth.get_balance('0x742d35Cc6635C0532925a3b8D5c0d9E3C4B3c8')

263

```

264

265

### Transaction Signing Middleware

266

267

```python

268

from web3 import Web3

269

from web3.middleware import SignAndSendRawMiddlewareBuilder

270

from eth_account import Account

271

272

# Create account for signing

273

account = Account.create()

274

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

275

276

# Add signing middleware

277

signing_middleware = SignAndSendRawMiddlewareBuilder(account)

278

w3.middleware_onion.add(signing_middleware, 'signing')

279

280

# Transactions will be automatically signed

281

tx_hash = w3.eth.send_transaction({

282

'from': account.address,

283

'to': '0x742d35Cc6635C0532925a3b8D5c0d9E3C4B3c8',

284

'value': w3.to_wei(1, 'ether'),

285

'gas': 21000

286

})

287

288

print(f"Signed transaction hash: {tx_hash.hex()}")

289

```

290

291

### Gas Price Strategy Middleware

292

293

```python

294

from web3 import Web3

295

from web3.gas_strategies.time_based import construct_time_based_gas_price_strategy

296

297

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

298

299

# Create time-based gas price strategy

300

gas_strategy = construct_time_based_gas_price_strategy(

301

max_wait_seconds=60,

302

sample_size=5

303

)

304

305

# Set gas price strategy

306

w3.eth.set_gas_price_strategy(gas_strategy)

307

308

# Gas prices will be determined by strategy

309

transaction = {

310

'from': w3.eth.accounts[0],

311

'to': '0x742d35Cc6635C0532925a3b8D5c0d9E3C4B3c8',

312

'value': w3.to_wei(1, 'ether'),

313

'gas': 21000

314

# gasPrice automatically set by strategy

315

}

316

317

tx_hash = w3.eth.send_transaction(transaction)

318

```

319

320

### Stale Block Check Middleware

321

322

```python

323

from web3 import Web3

324

from web3.middleware import StalecheckMiddlewareBuilder

325

326

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

327

328

# Add stale block check (fail if block is >60 seconds old)

329

stalecheck_middleware = StalecheckMiddlewareBuilder(allowable_delay=60)

330

w3.middleware_onion.add(stalecheck_middleware, 'stalecheck')

331

332

# Requests will fail if connected to stale node

333

try:

334

balance = w3.eth.get_balance('0x742d35Cc6635C0532925a3b8D5c0d9E3C4B3c8')

335

print(f"Balance: {balance}")

336

except Exception as e:

337

print(f"Node appears to be stale: {e}")

338

```

339

340

### Response Formatting Middleware

341

342

```python

343

from web3 import Web3

344

from web3.middleware import FormattingMiddlewareBuilder

345

346

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

347

348

# Add response formatting

349

formatting_middleware = FormattingMiddlewareBuilder()

350

w3.middleware_onion.add(formatting_middleware, 'formatting')

351

352

# Responses will be formatted for Python consumption

353

block = w3.eth.get_block('latest')

354

print(f"Block timestamp: {block.timestamp}") # Properly formatted

355

```

356

357

### Middleware Stack Management

358

359

```python

360

from web3 import Web3

361

362

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

363

364

# View current middleware stack

365

print("Current middleware:")

366

for name, middleware in w3.middleware_onion:

367

print(f" {name}: {middleware}")

368

369

# Remove specific middleware

370

w3.middleware_onion.remove('validation')

371

372

# Replace middleware

373

new_validation = lambda make_request, w3: make_request

374

w3.middleware_onion.replace('validation', new_validation)

375

376

# Clear all middleware (be careful!)

377

# w3.middleware_onion.clear()

378

```

379

380

### Async Middleware

381

382

```python

383

import asyncio

384

from web3 import AsyncWeb3

385

386

async def async_logging_middleware(make_request, async_w3):

387

"""Async logging middleware."""

388

async def middleware(method, params):

389

print(f"Async request: {method}")

390

response = await make_request(method, params)

391

print(f"Async response received")

392

return response

393

return middleware

394

395

async def main():

396

w3 = AsyncWeb3(AsyncWeb3.AsyncHTTPProvider('http://localhost:8545'))

397

w3.middleware_onion.add(async_logging_middleware, 'async_logging')

398

399

# Middleware will process async requests

400

balance = await w3.eth.get_balance('0x742d35Cc6635C0532925a3b8D5c0d9E3C4B3c8')

401

print(f"Balance: {balance}")

402

403

asyncio.run(main())

404

```

405

406

### Error Handling Middleware

407

408

```python

409

from web3 import Web3

410

from web3.exceptions import Web3Exception

411

412

def error_handling_middleware(make_request, w3):

413

"""Add custom error handling."""

414

def middleware(method, params):

415

try:

416

return make_request(method, params)

417

except Exception as e:

418

print(f"Request failed: {method} - {e}")

419

# Could implement retry logic, fallback providers, etc.

420

raise Web3Exception(f"Enhanced error info: {e}")

421

return middleware

422

423

w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

424

w3.middleware_onion.add(error_handling_middleware, 'error_handling')

425

```