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

json-rpc.mddocs/

0

# JSON-RPC Protocol

1

2

Complete JSON-RPC protocol utilities including request/response validation, batch operations, and comprehensive type guards. These functions provide robust JSON-RPC protocol handling for Web3 applications.

3

4

## Capabilities

5

6

### Response Validation

7

8

#### Error Response Handling

9

10

```typescript { .api }

11

/**

12

* Checks if response has valid RPC error code

13

* @param rpcError - JSON-RPC response with error

14

* @returns true if error code is valid

15

*/

16

function isResponseRpcError(rpcError: JsonRpcResponseWithError): boolean;

17

```

18

19

#### Response Type Guards

20

21

```typescript { .api }

22

/**

23

* Type guard for response with result

24

* @param response - JSON-RPC response to check

25

* @returns true if response contains result

26

*/

27

function isResponseWithResult<Result, Error>(

28

response: JsonRpcResponse<Result, Error>

29

): response is JsonRpcResponseWithResult<Result>;

30

31

/**

32

* Type guard for response with error

33

* @param response - JSON-RPC response to check

34

* @returns true if response contains error

35

*/

36

function isResponseWithError<Error, Result>(

37

response: JsonRpcResponse<Result, Error>

38

): response is JsonRpcResponseWithError<Error>;

39

40

/**

41

* Type guard for notification response

42

* @param response - Response to check

43

* @returns true if response is a notification

44

*/

45

function isResponseWithNotification<Result>(

46

response: JsonRpcNotification<Result> | JsonRpcSubscriptionResult

47

): response is JsonRpcNotification<Result>;

48

49

/**

50

* Type guard for subscription result

51

* @param response - Response to check

52

* @returns true if response is a subscription result

53

*/

54

function isSubscriptionResult<Result>(

55

response: JsonRpcNotification<Result> | JsonRpcSubscriptionResult

56

): response is JsonRpcSubscriptionResult;

57

```

58

59

#### Response Validation

60

61

```typescript { .api }

62

/**

63

* Validates JSON-RPC response format

64

* @param response - JSON-RPC response to validate

65

* @returns true if response is valid

66

*/

67

function validateResponse<Result, Error>(

68

response: JsonRpcResponse<Result, Error>

69

): boolean;

70

71

/**

72

* Checks if single/batch response is valid

73

* @param response - JSON-RPC response to check

74

* @returns true if response format is valid

75

*/

76

function isValidResponse<Result, Error>(

77

response: JsonRpcResponse<Result, Error>

78

): boolean;

79

```

80

81

### Batch Operations

82

83

#### Batch Type Guards

84

85

```typescript { .api }

86

/**

87

* Type guard for batch response

88

* @param response - Response to check

89

* @returns true if response is a batch response

90

*/

91

function isBatchResponse<Result, Error>(

92

response: JsonRpcResponse<Result, Error>

93

): response is JsonRpcBatchResponse<Result, Error>;

94

95

/**

96

* Type guard for batch request

97

* @param request - Request to check

98

* @returns true if request is a batch request

99

*/

100

function isBatchRequest(

101

request: JsonRpcBatchRequest | JsonRpcRequest<unknown> | JsonRpcOptionalRequest<unknown>

102

): request is JsonRpcBatchRequest;

103

```

104

105

#### Batch Payload Creation

106

107

```typescript { .api }

108

/**

109

* Converts requests to batch payload

110

* @param requests - Array of JSON-RPC requests

111

* @returns Batch request payload

112

*/

113

function toBatchPayload(requests: JsonRpcOptionalRequest<unknown>[]): JsonRpcBatchRequest;

114

```

115

116

### Request Management

117

118

#### Request ID Management

119

120

```typescript { .api }

121

/**

122

* Sets starting number for request IDs

123

* @param start - Starting ID number (undefined for auto-increment)

124

*/

125

function setRequestIdStart(start: number | undefined): void;

126

```

127

128

#### Payload Conversion

129

130

```typescript { .api }

131

/**

132

* Converts request to payload format

133

* @param request - JSON-RPC request (with optional ID)

134

* @returns Complete JSON-RPC payload with ID

135

*/

136

function toPayload<ParamType>(

137

request: JsonRpcOptionalRequest<ParamType>

138

): JsonRpcPayload<ParamType>;

139

```

140

141

## Usage Examples

142

143

### Request/Response Handling

144

145

```typescript

146

import {

147

toPayload, validateResponse, isResponseWithResult,

148

isResponseWithError, toBatchPayload

149

} from "web3-utils";

150

151

// Create single request payload

152

const request = {

153

method: "eth_getBalance",

154

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

155

};

156

157

const payload = toPayload(request);

158

// Result: { jsonrpc: "2.0", id: 1, method: "eth_getBalance", params: [...] }

159

160

// Validate and handle response

161

async function handleJsonRpcResponse(response: any) {

162

if (!validateResponse(response)) {

163

throw new Error('Invalid JSON-RPC response format');

164

}

165

166

if (isResponseWithResult(response)) {

167

console.log('Success result:', response.result);

168

return response.result;

169

} else if (isResponseWithError(response)) {

170

console.error('RPC Error:', response.error);

171

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

172

}

173

}

174

175

// Usage with fetch

176

const response = await fetch('/rpc', {

177

method: 'POST',

178

headers: { 'Content-Type': 'application/json' },

179

body: JSON.stringify(payload)

180

});

181

182

const jsonResponse = await response.json();

183

const result = await handleJsonRpcResponse(jsonResponse);

184

```

185

186

### Batch Operations

187

188

```typescript

189

import { toBatchPayload, isBatchResponse, isValidResponse } from "web3-utils";

190

191

// Create batch request

192

const requests = [

193

{ method: "eth_getBalance", params: ["0x742E4C5b469F50A4a8b399D4915C1fc93d15651B", "latest"] },

194

{ method: "eth_getTransactionCount", params: ["0x742E4C5b469F50A4a8b399D4915C1fc93d15651B", "latest"] },

195

{ method: "eth_gasPrice", params: [] }

196

];

197

198

const batchPayload = toBatchPayload(requests);

199

// Result: Array of payloads with unique IDs

200

201

// Handle batch response

202

async function handleBatchResponse(response: any) {

203

if (!isValidResponse(response)) {

204

throw new Error('Invalid response format');

205

}

206

207

if (isBatchResponse(response)) {

208

const results = [];

209

for (const singleResponse of response) {

210

if (isResponseWithResult(singleResponse)) {

211

results.push(singleResponse.result);

212

} else if (isResponseWithError(singleResponse)) {

213

results.push({ error: singleResponse.error });

214

}

215

}

216

return results;

217

} else {

218

// Single response

219

return [await handleJsonRpcResponse(response)];

220

}

221

}

222

223

// Usage

224

const batchResponse = await fetch('/rpc', {

225

method: 'POST',

226

headers: { 'Content-Type': 'application/json' },

227

body: JSON.stringify(batchPayload)

228

});

229

230

const jsonBatchResponse = await batchResponse.json();

231

const results = await handleBatchResponse(jsonBatchResponse);

232

```

233

234

### Subscription Handling

235

236

```typescript

237

import {

238

isResponseWithNotification, isSubscriptionResult

239

} from "web3-utils";

240

241

// WebSocket message handler

242

function handleWebSocketMessage(data: any) {

243

try {

244

const message = JSON.parse(data);

245

246

if (isResponseWithNotification(message)) {

247

console.log('Received notification:', message.method, message.params);

248

// Handle notification (e.g., new block, pending transaction)

249

} else if (isSubscriptionResult(message)) {

250

console.log('Subscription data:', message.params);

251

// Handle subscription data

252

} else {

253

// Regular JSON-RPC response

254

return handleJsonRpcResponse(message);

255

}

256

} catch (error) {

257

console.error('Failed to parse WebSocket message:', error);

258

}

259

}

260

```

261

262

### Request ID Management

263

264

```typescript

265

import { setRequestIdStart, toPayload } from "web3-utils";

266

267

// Set custom starting ID

268

setRequestIdStart(1000);

269

270

const request1 = toPayload({ method: "eth_blockNumber" });

271

console.log(request1.id); // 1000

272

273

const request2 = toPayload({ method: "eth_gasPrice" });

274

console.log(request2.id); // 1001

275

276

// Reset to auto-increment

277

setRequestIdStart(undefined);

278

279

const request3 = toPayload({ method: "eth_chainId" });

280

console.log(request3.id); // Auto-generated

281

```

282

283

### Error Handling Patterns

284

285

```typescript

286

import {

287

isResponseRpcError, isResponseWithError, validateResponse

288

} from "web3-utils";

289

290

async function robustJsonRpcCall(request: any) {

291

const payload = toPayload(request);

292

293

try {

294

const response = await fetch('/rpc', {

295

method: 'POST',

296

headers: { 'Content-Type': 'application/json' },

297

body: JSON.stringify(payload)

298

});

299

300

if (!response.ok) {

301

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

302

}

303

304

const jsonResponse = await response.json();

305

306

// Validate response format

307

if (!validateResponse(jsonResponse)) {

308

throw new Error('Invalid JSON-RPC response format');

309

}

310

311

// Check for RPC errors

312

if (isResponseWithError(jsonResponse)) {

313

if (isResponseRpcError(jsonResponse)) {

314

// Standard RPC error

315

const { code, message, data } = jsonResponse.error;

316

throw new Error(`RPC Error ${code}: ${message}${data ? ` (${JSON.stringify(data)})` : ''}`);

317

} else {

318

// Non-standard error

319

throw new Error(`Invalid RPC error: ${JSON.stringify(jsonResponse.error)}`);

320

}

321

}

322

323

if (isResponseWithResult(jsonResponse)) {

324

return jsonResponse.result;

325

}

326

327

throw new Error('Response contains neither result nor error');

328

329

} catch (error) {

330

console.error('JSON-RPC call failed:', error);

331

throw error;

332

}

333

}

334

```

335

336

## Types

337

338

The JSON-RPC utilities work with standard JSON-RPC type definitions:

339

340

```typescript { .api }

341

// Basic JSON-RPC structures

342

interface JsonRpcRequest<T> {

343

jsonrpc: "2.0";

344

id: number | string;

345

method: string;

346

params?: T;

347

}

348

349

interface JsonRpcOptionalRequest<T> {

350

method: string;

351

params?: T;

352

id?: number | string;

353

}

354

355

interface JsonRpcPayload<T> {

356

jsonrpc: "2.0";

357

id: number | string;

358

method: string;

359

params?: T;

360

}

361

362

interface JsonRpcResponseWithResult<T> {

363

jsonrpc: "2.0";

364

id: number | string;

365

result: T;

366

}

367

368

interface JsonRpcResponseWithError<T = any> {

369

jsonrpc: "2.0";

370

id: number | string;

371

error: {

372

code: number;

373

message: string;

374

data?: T;

375

};

376

}

377

378

type JsonRpcResponse<Result, Error> =

379

| JsonRpcResponseWithResult<Result>

380

| JsonRpcResponseWithError<Error>;

381

382

type JsonRpcBatchRequest = JsonRpcRequest<unknown>[];

383

type JsonRpcBatchResponse<Result, Error> = JsonRpcResponse<Result, Error>[];

384

```