Collection of utility functions used in web3.js for Ethereum dApp development
—
String padding, two's complement conversion, object merging, and Uint8Array operations for data processing. These utilities provide essential data manipulation capabilities for blockchain development.
/**
* Adds padding to left of string/number
* @param value - Value to pad (Numbers type)
* @param characterAmount - Total character length after padding
* @param sign - Padding character (default: "0")
* @returns Left-padded string
*/
function padLeft(value: Numbers, characterAmount: number, sign?: string): string;
/**
* Alias for padLeft
*/
const leftPad = padLeft;/**
* Adds padding to right of string/number
* @param value - Value to pad (Numbers type)
* @param characterAmount - Total character length after padding
* @param sign - Padding character (default: "0")
* @returns Right-padded string
*/
function padRight(value: Numbers, characterAmount: number, sign?: string): string;
/**
* Alias for padRight
*/
const rightPad = padRight;/**
* Converts negative number to two's complement hex representation
* @param value - Number to convert (Numbers type)
* @param nibbleWidth - Width in nibbles (4-bit units), optional
* @returns Two's complement hex string
*/
function toTwosComplement(value: Numbers, nibbleWidth?: number): string;/**
* Converts two's complement hex to decimal number
* @param value - Two's complement hex value (Numbers type)
* @param nibbleWidth - Width in nibbles (4-bit units), optional
* @returns Decimal number or bigint
*/
function fromTwosComplement(value: Numbers, nibbleWidth?: number): number | bigint;/**
* Deep merges multiple objects into destination object
* @param destination - Target object to merge into
* @param sources - Source objects to merge from
* @returns Merged object with all properties
*/
function mergeDeep(
destination: Record<string, unknown>,
...sources: Record<string, unknown>[]
): Record<string, unknown>;/**
* Type guard for Uint8Array (including Node.js Buffer)
* @param data - Data to check
* @returns true if data is Uint8Array or Buffer
*/
function isUint8Array(data: unknown | Uint8Array): data is Uint8Array;/**
* Concatenates multiple Uint8Arrays into single array
* @param parts - Uint8Array parts to concatenate
* @returns New Uint8Array with concatenated data
*/
function uint8ArrayConcat(...parts: Uint8Array[]): Uint8Array;/**
* Checks if two Uint8Arrays have same content
* @param a - First Uint8Array
* @param b - Second Uint8Array
* @returns true if arrays have identical content
*/
function uint8ArrayEquals(a: Uint8Array, b: Uint8Array): boolean;/**
* Parser for chunked JSON-RPC responses
* Handles streaming response data and event emission
*/
class ChunkResponseParser {
/**
* Creates new chunk response parser
* @param eventEmitter - EventEmitter for parsed responses
* @param autoReconnect - Whether to auto-reconnect on errors
*/
constructor(eventEmitter: EventEmitter, autoReconnect: boolean);
/**
* Handles parsing errors
* @param clearQueues - Optional function to clear request queues
*/
onError(clearQueues?: () => void): void;
/**
* Parses response data string into JSON-RPC responses
* @param data - Raw response data string
* @returns Array of parsed JSON-RPC responses
*/
parseResponse(data: string): JsonRpcResponse[];
}import { padLeft, padRight } from "web3-utils";
// Left padding with zeros (default)
const paddedHex = padLeft("0x1a", 8); // "0x00001a"
const paddedNumber = padLeft(26, 6); // "000026"
// Left padding with custom character
const paddedCustom = padLeft("abc", 10, " "); // " abc"
// Right padding
const rightPaddedHex = padRight("0x1a", 8); // "0x1a0000"
const rightPaddedString = padRight("hello", 10, "."); // "hello....."
// Common use case: address padding
const address = "0x742E4C5b469F50A4a8b399D4915C1fc93d15651B";
const paddedAddress = padLeft(address, 66); // Pad to 32 bytes + "0x"import { toTwosComplement, fromTwosComplement } from "web3-utils";
// Convert negative number to two's complement
const negative = -123;
const twosComp = toTwosComplement(negative); // Two's complement representation
const twosCompFixed = toTwosComplement(negative, 8); // Fixed 8-nibble width
// Convert back from two's complement
const original = fromTwosComplement(twosComp); // -123
// Working with different bit widths
const value8bit = toTwosComplement(-1, 2); // 8-bit: "0xff"
const value16bit = toTwosComplement(-1, 4); // 16-bit: "0xffff"
const value32bit = toTwosComplement(-1, 8); // 32-bit: "0xffffffff"
// Convert back with same width
const decoded8bit = fromTwosComplement(value8bit, 2); // -1
const decoded16bit = fromTwosComplement(value16bit, 4); // -1import { mergeDeep } from "web3-utils";
// Basic object merge
const target = { a: 1, b: { x: 10 } };
const source1 = { b: { y: 20 }, c: 3 };
const source2 = { b: { z: 30 }, d: 4 };
const merged = mergeDeep(target, source1, source2);
// Result: { a: 1, b: { x: 10, y: 20, z: 30 }, c: 3, d: 4 }
// Configuration merging example
const defaultConfig = {
network: {
chainId: 1,
timeout: 5000,
retries: 3
},
logging: {
level: 'info',
format: 'json'
}
};
const userConfig = {
network: {
timeout: 10000,
endpoint: 'https://custom-rpc.com'
},
logging: {
level: 'debug'
}
};
const finalConfig = mergeDeep({}, defaultConfig, userConfig);
// Result: Merged configuration with user overridesimport { isUint8Array, uint8ArrayConcat, uint8ArrayEquals } from "web3-utils";
// Type checking
const data1 = new Uint8Array([1, 2, 3]);
const data2 = Buffer.from([4, 5, 6]); // Node.js Buffer
const data3 = [7, 8, 9]; // Regular array
console.log(isUint8Array(data1)); // true
console.log(isUint8Array(data2)); // true (Buffer extends Uint8Array)
console.log(isUint8Array(data3)); // false
// Concatenation
const part1 = new Uint8Array([1, 2, 3]);
const part2 = new Uint8Array([4, 5, 6]);
const part3 = new Uint8Array([7, 8, 9]);
const combined = uint8ArrayConcat(part1, part2, part3);
// Result: Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9])
// Equality checking
const array1 = new Uint8Array([1, 2, 3, 4]);
const array2 = new Uint8Array([1, 2, 3, 4]);
const array3 = new Uint8Array([1, 2, 3, 5]);
console.log(uint8ArrayEquals(array1, array2)); // true
console.log(uint8ArrayEquals(array1, array3)); // false
// Common blockchain use case: signature concatenation
const r = new Uint8Array(32); // 32 bytes
const s = new Uint8Array(32); // 32 bytes
const v = new Uint8Array([27]); // 1 byte
const signature = uint8ArrayConcat(r, s, v); // 65-byte signatureimport { ChunkResponseParser, EventEmitter } from "web3-utils";
// Set up parser for streaming responses
const emitter = new EventEmitter();
const parser = new ChunkResponseParser(emitter, true);
// Handle parsed responses
emitter.on('message', (response) => {
console.log('Parsed response:', response);
});
emitter.on('error', (error) => {
console.error('Parser error:', error);
});
// Parse chunked data (e.g., from WebSocket or HTTP streaming)
const chunkData = `{"jsonrpc":"2.0","id":1,"result":"0x1"}\n{"jsonrpc":"2.0","id":2,"result":"0x2"}`;
const responses = parser.parseResponse(chunkData);
// responses will contain parsed JSON-RPC objects
responses.forEach(response => {
console.log('Individual response:', response);
});import {
padLeft, padRight, mergeDeep, uint8ArrayConcat,
toTwosComplement, fromTwosComplement
} from "web3-utils";
// Smart contract data encoding
function encodeContractCall(methodId: string, params: Uint8Array[]) {
// Method ID is first 4 bytes (8 hex chars + 0x)
const paddedMethodId = padRight(methodId, 10, "0");
// Encode each parameter to 32 bytes
const encodedParams = params.map(param => {
const hex = Array.from(param, byte => byte.toString(16).padStart(2, '0')).join('');
return padLeft(`0x${hex}`, 66, "0"); // 32 bytes = 64 hex chars + "0x"
});
return paddedMethodId + encodedParams.map(p => p.slice(2)).join('');
}
// Configuration system with deep merging
class ConfigManager {
private config: Record<string, unknown> = {};
loadDefaults(defaults: Record<string, unknown>) {
this.config = mergeDeep({}, defaults);
}
loadUserConfig(userConfig: Record<string, unknown>) {
this.config = mergeDeep(this.config, userConfig);
}
loadEnvironmentOverrides(envConfig: Record<string, unknown>) {
this.config = mergeDeep(this.config, envConfig);
}
getConfig(): Record<string, unknown> {
return this.config;
}
}
// Binary data manipulation
function processSignature(r: Uint8Array, s: Uint8Array, recovery: number) {
// Ensure r and s are 32 bytes
const paddedR = r.length < 32 ? uint8ArrayConcat(new Uint8Array(32 - r.length), r) : r;
const paddedS = s.length < 32 ? uint8ArrayConcat(new Uint8Array(32 - s.length), s) : s;
// Recovery value (v) is typically 27 or 28
const v = new Uint8Array([recovery + 27]);
return uint8ArrayConcat(paddedR, paddedS, v);
}Install with Tessl CLI
npx tessl i tessl/npm-web3-utils