CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-web3-utils

Collection of utility functions used in web3.js for Ethereum dApp development

Pending
Overview
Eval results
Files

json-rpc.mddocs/

JSON-RPC Protocol

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.

Capabilities

Response Validation

Error Response Handling

/**
 * Checks if response has valid RPC error code
 * @param rpcError - JSON-RPC response with error
 * @returns true if error code is valid
 */
function isResponseRpcError(rpcError: JsonRpcResponseWithError): boolean;

Response Type Guards

/**
 * Type guard for response with result
 * @param response - JSON-RPC response to check
 * @returns true if response contains result
 */
function isResponseWithResult<Result, Error>(
  response: JsonRpcResponse<Result, Error>
): response is JsonRpcResponseWithResult<Result>;

/**
 * Type guard for response with error
 * @param response - JSON-RPC response to check
 * @returns true if response contains error
 */
function isResponseWithError<Error, Result>(
  response: JsonRpcResponse<Result, Error>
): response is JsonRpcResponseWithError<Error>;

/**
 * Type guard for notification response
 * @param response - Response to check
 * @returns true if response is a notification
 */
function isResponseWithNotification<Result>(
  response: JsonRpcNotification<Result> | JsonRpcSubscriptionResult
): response is JsonRpcNotification<Result>;

/**
 * Type guard for subscription result
 * @param response - Response to check
 * @returns true if response is a subscription result
 */
function isSubscriptionResult<Result>(
  response: JsonRpcNotification<Result> | JsonRpcSubscriptionResult
): response is JsonRpcSubscriptionResult;

Response Validation

/**
 * Validates JSON-RPC response format
 * @param response - JSON-RPC response to validate
 * @returns true if response is valid
 */
function validateResponse<Result, Error>(
  response: JsonRpcResponse<Result, Error>
): boolean;

/**
 * Checks if single/batch response is valid
 * @param response - JSON-RPC response to check
 * @returns true if response format is valid
 */
function isValidResponse<Result, Error>(
  response: JsonRpcResponse<Result, Error>
): boolean;

Batch Operations

Batch Type Guards

/**
 * Type guard for batch response
 * @param response - Response to check
 * @returns true if response is a batch response
 */
function isBatchResponse<Result, Error>(
  response: JsonRpcResponse<Result, Error>
): response is JsonRpcBatchResponse<Result, Error>;

/**
 * Type guard for batch request
 * @param request - Request to check
 * @returns true if request is a batch request
 */
function isBatchRequest(
  request: JsonRpcBatchRequest | JsonRpcRequest<unknown> | JsonRpcOptionalRequest<unknown>
): request is JsonRpcBatchRequest;

Batch Payload Creation

/**
 * Converts requests to batch payload
 * @param requests - Array of JSON-RPC requests
 * @returns Batch request payload
 */
function toBatchPayload(requests: JsonRpcOptionalRequest<unknown>[]): JsonRpcBatchRequest;

Request Management

Request ID Management

/**
 * Sets starting number for request IDs
 * @param start - Starting ID number (undefined for auto-increment)
 */
function setRequestIdStart(start: number | undefined): void;

Payload Conversion

/**
 * Converts request to payload format
 * @param request - JSON-RPC request (with optional ID)
 * @returns Complete JSON-RPC payload with ID
 */
function toPayload<ParamType>(
  request: JsonRpcOptionalRequest<ParamType>
): JsonRpcPayload<ParamType>;

Usage Examples

Request/Response Handling

import { 
  toPayload, validateResponse, isResponseWithResult, 
  isResponseWithError, toBatchPayload 
} from "web3-utils";

// Create single request payload
const request = {
  method: "eth_getBalance",
  params: ["0x742E4C5b469F50A4a8b399D4915C1fc93d15651B", "latest"]
};

const payload = toPayload(request);
// Result: { jsonrpc: "2.0", id: 1, method: "eth_getBalance", params: [...] }

// Validate and handle response
async function handleJsonRpcResponse(response: any) {
  if (!validateResponse(response)) {
    throw new Error('Invalid JSON-RPC response format');
  }

  if (isResponseWithResult(response)) {
    console.log('Success result:', response.result);
    return response.result;
  } else if (isResponseWithError(response)) {
    console.error('RPC Error:', response.error);
    throw new Error(`RPC Error ${response.error.code}: ${response.error.message}`);
  }
}

// Usage with fetch
const response = await fetch('/rpc', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload)
});

const jsonResponse = await response.json();
const result = await handleJsonRpcResponse(jsonResponse);

Batch Operations

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

// Create batch request
const requests = [
  { method: "eth_getBalance", params: ["0x742E4C5b469F50A4a8b399D4915C1fc93d15651B", "latest"] },
  { method: "eth_getTransactionCount", params: ["0x742E4C5b469F50A4a8b399D4915C1fc93d15651B", "latest"] },
  { method: "eth_gasPrice", params: [] }
];

const batchPayload = toBatchPayload(requests);
// Result: Array of payloads with unique IDs

// Handle batch response
async function handleBatchResponse(response: any) {
  if (!isValidResponse(response)) {
    throw new Error('Invalid response format');
  }

  if (isBatchResponse(response)) {
    const results = [];
    for (const singleResponse of response) {
      if (isResponseWithResult(singleResponse)) {
        results.push(singleResponse.result);
      } else if (isResponseWithError(singleResponse)) {
        results.push({ error: singleResponse.error });
      }
    }
    return results;
  } else {
    // Single response
    return [await handleJsonRpcResponse(response)];
  }
}

// Usage
const batchResponse = await fetch('/rpc', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(batchPayload)
});

const jsonBatchResponse = await batchResponse.json();
const results = await handleBatchResponse(jsonBatchResponse);

Subscription Handling

import { 
  isResponseWithNotification, isSubscriptionResult 
} from "web3-utils";

// WebSocket message handler
function handleWebSocketMessage(data: any) {
  try {
    const message = JSON.parse(data);

    if (isResponseWithNotification(message)) {
      console.log('Received notification:', message.method, message.params);
      // Handle notification (e.g., new block, pending transaction)
    } else if (isSubscriptionResult(message)) {
      console.log('Subscription data:', message.params);
      // Handle subscription data
    } else {
      // Regular JSON-RPC response
      return handleJsonRpcResponse(message);
    }
  } catch (error) {
    console.error('Failed to parse WebSocket message:', error);
  }
}

Request ID Management

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

// Set custom starting ID
setRequestIdStart(1000);

const request1 = toPayload({ method: "eth_blockNumber" });
console.log(request1.id); // 1000

const request2 = toPayload({ method: "eth_gasPrice" });
console.log(request2.id); // 1001

// Reset to auto-increment
setRequestIdStart(undefined);

const request3 = toPayload({ method: "eth_chainId" });
console.log(request3.id); // Auto-generated

Error Handling Patterns

import { 
  isResponseRpcError, isResponseWithError, validateResponse 
} from "web3-utils";

async function robustJsonRpcCall(request: any) {
  const payload = toPayload(request);
  
  try {
    const response = await fetch('/rpc', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload)
    });

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

    const jsonResponse = await response.json();

    // Validate response format
    if (!validateResponse(jsonResponse)) {
      throw new Error('Invalid JSON-RPC response format');
    }

    // Check for RPC errors
    if (isResponseWithError(jsonResponse)) {
      if (isResponseRpcError(jsonResponse)) {
        // Standard RPC error
        const { code, message, data } = jsonResponse.error;
        throw new Error(`RPC Error ${code}: ${message}${data ? ` (${JSON.stringify(data)})` : ''}`);
      } else {
        // Non-standard error
        throw new Error(`Invalid RPC error: ${JSON.stringify(jsonResponse.error)}`);
      }
    }

    if (isResponseWithResult(jsonResponse)) {
      return jsonResponse.result;
    }

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

  } catch (error) {
    console.error('JSON-RPC call failed:', error);
    throw error;
  }
}

Types

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

// Basic JSON-RPC structures
interface JsonRpcRequest<T> {
  jsonrpc: "2.0";
  id: number | string;
  method: string;
  params?: T;
}

interface JsonRpcOptionalRequest<T> {
  method: string;
  params?: T;
  id?: number | string;
}

interface JsonRpcPayload<T> {
  jsonrpc: "2.0";
  id: number | string;
  method: string;
  params?: T;
}

interface JsonRpcResponseWithResult<T> {
  jsonrpc: "2.0";
  id: number | string;
  result: T;
}

interface JsonRpcResponseWithError<T = any> {
  jsonrpc: "2.0";
  id: number | string;
  error: {
    code: number;
    message: string;
    data?: T;
  };
}

type JsonRpcResponse<Result, Error> = 
  | JsonRpcResponseWithResult<Result> 
  | JsonRpcResponseWithError<Error>;

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

Install with Tessl CLI

npx tessl i tessl/npm-web3-utils

docs

conversion.md

data-manipulation.md

events.md

hashing.md

index.md

json-rpc.md

promises.md

providers.md

random-validation.md

tile.json