or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

conversion.mddata-manipulation.mdevents.mdhashing.mdindex.mdjson-rpc.mdpromises.mdproviders.mdrandom-validation.md

providers.mddocs/

0

# Provider Abstractions

1

2

Abstract base classes for implementing EIP-1193 compatible providers and socket-based connections with automatic reconnection support. These classes provide the foundation for building Web3 providers.

3

4

## Capabilities

5

6

### EIP-1193 Provider

7

8

Abstract implementation of the EIP-1193 provider standard.

9

10

```typescript { .api }

11

/**

12

* Abstract EIP-1193 provider implementation

13

* Extends Web3BaseProvider with EIP-1193 specific functionality

14

*/

15

abstract class Eip1193Provider<API extends Web3APISpec = EthExecutionAPI> extends Web3BaseProvider<API> {

16

/**

17

* Called when provider connects

18

* Should be implemented by concrete providers

19

*/

20

protected _onConnect(): void;

21

22

/**

23

* Called when provider disconnects

24

* Should be implemented by concrete providers

25

* @param code - Disconnection code

26

* @param data - Optional disconnection data

27

*/

28

protected _onDisconnect(code: number, data?: unknown): void;

29

}

30

```

31

32

### Socket Provider

33

34

Abstract socket-based provider with reconnection capabilities.

35

36

```typescript { .api }

37

/**

38

* Abstract socket-based provider for WebSocket, IPC, etc.

39

* Provides reconnection logic and socket management

40

*/

41

abstract class SocketProvider<

42

MessageEvent,

43

CloseEvent,

44

ErrorEvent,

45

API extends Web3APISpec = EthExecutionAPI

46

> extends Eip1193Provider<API> {

47

/**

48

* Socket connection accessor

49

* @returns Current socket connection

50

*/

51

get SocketConnection(): unknown;

52

53

/**

54

* Creates new socket provider

55

* @param socketPath - Path or URL for socket connection

56

* @param socketOptions - Socket-specific options

57

* @param reconnectOptions - Reconnection configuration

58

*/

59

constructor(

60

socketPath: string,

61

socketOptions?: unknown,

62

reconnectOptions?: Partial<ReconnectOptions>

63

);

64

65

/**

66

* Establishes socket connection

67

*/

68

connect(): void;

69

70

/**

71

* Closes socket connection

72

* @param code - Close code

73

* @param data - Close reason

74

*/

75

disconnect(code?: number, data?: string): void;

76

77

/**

78

* Safely disconnects with timeout

79

* @param code - Close code

80

* @param data - Close reason

81

* @param forceDisconnect - Force disconnect after timeout

82

* @param ms - Timeout in milliseconds

83

* @returns Promise that resolves when disconnected

84

*/

85

safeDisconnect(code?: number, data?: string, forceDisconnect?: boolean, ms?: number): Promise<void>;

86

87

/**

88

* Resets provider state and connection

89

*/

90

reset(): void;

91

92

/**

93

* Gets pending request queue size

94

* @returns Number of pending requests

95

*/

96

getPendingRequestQueueSize(): number;

97

98

/**

99

* Gets sent requests queue size

100

* @returns Number of sent requests awaiting response

101

*/

102

getSentRequestsQueueSize(): number;

103

104

/**

105

* Checks if provider supports subscriptions

106

* @returns true if subscriptions are supported

107

*/

108

supportsSubscriptions(): boolean;

109

110

/**

111

* Clears request queues

112

* @param event - Optional connection event context

113

*/

114

clearQueues(event?: ConnectionEvent): void;

115

116

/**

117

* Sends JSON-RPC request

118

* @param request - Web3 API payload

119

* @returns Promise resolving to JSON-RPC response

120

*/

121

request<Method, ResultType>(

122

request: Web3APIPayload<API, Method>

123

): Promise<JsonRpcResponseWithResult<ResultType>>;

124

125

// Event listener methods inherited from EventEmitter

126

on(event: string, listener: Function): this;

127

once(event: string, listener: Function): this;

128

removeListener(event: string, listener: Function): this;

129

removeAllListeners(event?: string): this;

130

}

131

```

132

133

### Reconnection Options

134

135

```typescript { .api }

136

/**

137

* Configuration for automatic reconnection

138

*/

139

type ReconnectOptions = {

140

/**

141

* Whether to automatically reconnect on connection loss

142

*/

143

autoReconnect: boolean;

144

145

/**

146

* Delay between reconnection attempts in milliseconds

147

*/

148

delay: number;

149

150

/**

151

* Maximum number of reconnection attempts

152

*/

153

maxAttempts: number;

154

};

155

```

156

157

## Usage Examples

158

159

### Custom WebSocket Provider

160

161

```typescript

162

import { SocketProvider, ReconnectOptions } from "web3-utils";

163

164

class CustomWebSocketProvider extends SocketProvider<MessageEvent, CloseEvent, ErrorEvent> {

165

private ws: WebSocket | null = null;

166

167

constructor(url: string, options?: WebSocketOptions, reconnectOptions?: Partial<ReconnectOptions>) {

168

super(url, options, reconnectOptions);

169

}

170

171

// Implement required abstract methods

172

get SocketConnection() {

173

return this.ws;

174

}

175

176

connect(): void {

177

if (this.ws?.readyState === WebSocket.OPEN) {

178

return;

179

}

180

181

this.ws = new WebSocket(this.socketPath);

182

183

this.ws.onopen = (event) => {

184

this._onConnect();

185

this.emit('connect');

186

};

187

188

this.ws.onmessage = (event) => {

189

try {

190

const data = JSON.parse(event.data);

191

this.emit('message', data);

192

} catch (error) {

193

this.emit('error', error);

194

}

195

};

196

197

this.ws.onclose = (event) => {

198

this._onDisconnect(event.code, event.reason);

199

this.emit('disconnect', event.code, event.reason);

200

};

201

202

this.ws.onerror = (event) => {

203

this.emit('error', new Error('WebSocket error'));

204

};

205

}

206

207

disconnect(code?: number, data?: string): void {

208

if (this.ws) {

209

this.ws.close(code, data);

210

this.ws = null;

211

}

212

}

213

214

// Implement request sending

215

protected sendRequest(request: any): void {

216

if (this.ws?.readyState === WebSocket.OPEN) {

217

this.ws.send(JSON.stringify(request));

218

} else {

219

throw new Error('WebSocket not connected');

220

}

221

}

222

}

223

224

// Usage

225

const provider = new CustomWebSocketProvider('ws://localhost:8546', {}, {

226

autoReconnect: true,

227

delay: 5000,

228

maxAttempts: 5

229

});

230

231

provider.on('connect', () => {

232

console.log('Connected to WebSocket');

233

});

234

235

provider.on('disconnect', (code, reason) => {

236

console.log(`Disconnected: ${code} - ${reason}`);

237

});

238

239

provider.on('error', (error) => {

240

console.error('Provider error:', error);

241

});

242

243

provider.connect();

244

```

245

246

### Custom HTTP Provider

247

248

```typescript

249

import { Eip1193Provider } from "web3-utils";

250

251

class CustomHttpProvider extends Eip1193Provider {

252

private url: string;

253

private headers: Record<string, string>;

254

255

constructor(url: string, options?: { headers?: Record<string, string> }) {

256

super();

257

this.url = url;

258

this.headers = options?.headers || {};

259

}

260

261

protected _onConnect(): void {

262

// HTTP providers are always "connected"

263

this.emit('connect');

264

}

265

266

protected _onDisconnect(code: number, data?: unknown): void {

267

// HTTP providers don't really disconnect

268

this.emit('disconnect', code, data);

269

}

270

271

async request<Method, ResultType>(

272

request: Web3APIPayload<any, Method>

273

): Promise<JsonRpcResponseWithResult<ResultType>> {

274

try {

275

const response = await fetch(this.url, {

276

method: 'POST',

277

headers: {

278

'Content-Type': 'application/json',

279

...this.headers

280

},

281

body: JSON.stringify(request)

282

});

283

284

if (!response.ok) {

285

throw new Error(`HTTP ${response.status}: ${response.statusText}`);

286

}

287

288

const jsonResponse = await response.json();

289

290

if (jsonResponse.error) {

291

throw new Error(`RPC Error ${jsonResponse.error.code}: ${jsonResponse.error.message}`);

292

}

293

294

return jsonResponse;

295

} catch (error) {

296

this.emit('error', error);

297

throw error;

298

}

299

}

300

301

supportsSubscriptions(): boolean {

302

return false; // HTTP doesn't support subscriptions

303

}

304

}

305

306

// Usage

307

const httpProvider = new CustomHttpProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID', {

308

headers: {

309

'Authorization': 'Bearer your-token'

310

}

311

});

312

313

// Make requests

314

const result = await httpProvider.request({

315

method: 'eth_getBalance',

316

params: ['0x742E4C5b469F50A4a8b399D4915C1fc93d15651B', 'latest']

317

});

318

```

319

320

### Provider with Queue Management

321

322

```typescript

323

import { SocketProvider } from "web3-utils";

324

325

class ManagedSocketProvider extends SocketProvider<MessageEvent, CloseEvent, ErrorEvent> {

326

constructor(socketPath: string) {

327

super(socketPath, {}, {

328

autoReconnect: true,

329

delay: 2000,

330

maxAttempts: 10

331

});

332

333

// Monitor queue sizes

334

setInterval(() => {

335

const pending = this.getPendingRequestQueueSize();

336

const sent = this.getSentRequestsQueueSize();

337

338

if (pending > 100 || sent > 50) {

339

console.warn(`High queue sizes: pending=${pending}, sent=${sent}`);

340

}

341

}, 10000);

342

}

343

344

// Override to add queue management

345

async request<Method, ResultType>(

346

request: Web3APIPayload<any, Method>

347

): Promise<JsonRpcResponseWithResult<ResultType>> {

348

// Check queue size before adding request

349

if (this.getPendingRequestQueueSize() > 1000) {

350

throw new Error('Request queue full');

351

}

352

353

return super.request(request);

354

}

355

356

// Custom method to clear queues when needed

357

emergencyClearQueues(): void {

358

console.log('Emergency queue clear initiated');

359

this.clearQueues();

360

}

361

362

// Graceful shutdown

363

async shutdown(): Promise<void> {

364

console.log('Shutting down provider...');

365

366

// Wait for queues to empty or timeout

367

const maxWait = 30000; // 30 seconds

368

const startTime = Date.now();

369

370

while (

371

(this.getPendingRequestQueueSize() > 0 || this.getSentRequestsQueueSize() > 0) &&

372

(Date.now() - startTime) < maxWait

373

) {

374

await new Promise(resolve => setTimeout(resolve, 100));

375

}

376

377

await this.safeDisconnect(1000, 'Normal shutdown', true, 5000);

378

console.log('Provider shutdown complete');

379

}

380

}

381

```

382

383

## Common Usage Patterns

384

385

### Provider Factory

386

387

```typescript

388

import { SocketProvider, Eip1193Provider } from "web3-utils";

389

390

type ProviderConfig = {

391

type: 'http' | 'websocket' | 'ipc';

392

url: string;

393

options?: any;

394

reconnectOptions?: Partial<ReconnectOptions>;

395

};

396

397

function createProvider(config: ProviderConfig): Eip1193Provider {

398

switch (config.type) {

399

case 'http':

400

return new CustomHttpProvider(config.url, config.options);

401

case 'websocket':

402

return new CustomWebSocketProvider(config.url, config.options, config.reconnectOptions);

403

case 'ipc':

404

return new CustomIPCProvider(config.url, config.options, config.reconnectOptions);

405

default:

406

throw new Error(`Unsupported provider type: ${config.type}`);

407

}

408

}

409

410

// Usage

411

const provider = createProvider({

412

type: 'websocket',

413

url: 'ws://localhost:8546',

414

reconnectOptions: {

415

autoReconnect: true,

416

delay: 3000,

417

maxAttempts: 5

418

}

419

});

420

```

421

422

## Types

423

424

```typescript { .api }

425

// Provider-related types

426

type ConnectionEvent = 'connect' | 'disconnect' | 'error';

427

428

interface Web3APISpec {

429

[method: string]: {

430

Parameters: any[];

431

ReturnType: any;

432

};

433

}

434

435

interface Web3APIPayload<API extends Web3APISpec, Method extends keyof API> {

436

method: Method;

437

params: API[Method]['Parameters'];

438

}

439

440

interface Web3BaseProvider<API extends Web3APISpec> {

441

request<Method extends keyof API>(

442

request: Web3APIPayload<API, Method>

443

): Promise<API[Method]['ReturnType']>;

444

}

445

```