0
# String and Data Manipulation
1
2
String padding, two's complement conversion, object merging, and Uint8Array operations for data processing. These utilities provide essential data manipulation capabilities for blockchain development.
3
4
## Capabilities
5
6
### String Padding
7
8
#### Left Padding
9
10
```typescript { .api }
11
/**
12
* Adds padding to left of string/number
13
* @param value - Value to pad (Numbers type)
14
* @param characterAmount - Total character length after padding
15
* @param sign - Padding character (default: "0")
16
* @returns Left-padded string
17
*/
18
function padLeft(value: Numbers, characterAmount: number, sign?: string): string;
19
20
/**
21
* Alias for padLeft
22
*/
23
const leftPad = padLeft;
24
```
25
26
#### Right Padding
27
28
```typescript { .api }
29
/**
30
* Adds padding to right of string/number
31
* @param value - Value to pad (Numbers type)
32
* @param characterAmount - Total character length after padding
33
* @param sign - Padding character (default: "0")
34
* @returns Right-padded string
35
*/
36
function padRight(value: Numbers, characterAmount: number, sign?: string): string;
37
38
/**
39
* Alias for padRight
40
*/
41
const rightPad = padRight;
42
```
43
44
### Two's Complement Operations
45
46
#### To Two's Complement
47
48
```typescript { .api }
49
/**
50
* Converts negative number to two's complement hex representation
51
* @param value - Number to convert (Numbers type)
52
* @param nibbleWidth - Width in nibbles (4-bit units), optional
53
* @returns Two's complement hex string
54
*/
55
function toTwosComplement(value: Numbers, nibbleWidth?: number): string;
56
```
57
58
#### From Two's Complement
59
60
```typescript { .api }
61
/**
62
* Converts two's complement hex to decimal number
63
* @param value - Two's complement hex value (Numbers type)
64
* @param nibbleWidth - Width in nibbles (4-bit units), optional
65
* @returns Decimal number or bigint
66
*/
67
function fromTwosComplement(value: Numbers, nibbleWidth?: number): number | bigint;
68
```
69
70
### Object Operations
71
72
#### Deep Merge
73
74
```typescript { .api }
75
/**
76
* Deep merges multiple objects into destination object
77
* @param destination - Target object to merge into
78
* @param sources - Source objects to merge from
79
* @returns Merged object with all properties
80
*/
81
function mergeDeep(
82
destination: Record<string, unknown>,
83
...sources: Record<string, unknown>[]
84
): Record<string, unknown>;
85
```
86
87
### Uint8Array Operations
88
89
#### Type Guard
90
91
```typescript { .api }
92
/**
93
* Type guard for Uint8Array (including Node.js Buffer)
94
* @param data - Data to check
95
* @returns true if data is Uint8Array or Buffer
96
*/
97
function isUint8Array(data: unknown | Uint8Array): data is Uint8Array;
98
```
99
100
#### Array Concatenation
101
102
```typescript { .api }
103
/**
104
* Concatenates multiple Uint8Arrays into single array
105
* @param parts - Uint8Array parts to concatenate
106
* @returns New Uint8Array with concatenated data
107
*/
108
function uint8ArrayConcat(...parts: Uint8Array[]): Uint8Array;
109
```
110
111
#### Array Equality
112
113
```typescript { .api }
114
/**
115
* Checks if two Uint8Arrays have same content
116
* @param a - First Uint8Array
117
* @param b - Second Uint8Array
118
* @returns true if arrays have identical content
119
*/
120
function uint8ArrayEquals(a: Uint8Array, b: Uint8Array): boolean;
121
```
122
123
### Data Formatting and Parsing
124
125
#### Chunk Response Parser
126
127
```typescript { .api }
128
/**
129
* Parser for chunked JSON-RPC responses
130
* Handles streaming response data and event emission
131
*/
132
class ChunkResponseParser {
133
/**
134
* Creates new chunk response parser
135
* @param eventEmitter - EventEmitter for parsed responses
136
* @param autoReconnect - Whether to auto-reconnect on errors
137
*/
138
constructor(eventEmitter: EventEmitter, autoReconnect: boolean);
139
140
/**
141
* Handles parsing errors
142
* @param clearQueues - Optional function to clear request queues
143
*/
144
onError(clearQueues?: () => void): void;
145
146
/**
147
* Parses response data string into JSON-RPC responses
148
* @param data - Raw response data string
149
* @returns Array of parsed JSON-RPC responses
150
*/
151
parseResponse(data: string): JsonRpcResponse[];
152
}
153
```
154
155
## Usage Examples
156
157
### String Padding
158
159
```typescript
160
import { padLeft, padRight } from "web3-utils";
161
162
// Left padding with zeros (default)
163
const paddedHex = padLeft("0x1a", 8); // "0x00001a"
164
const paddedNumber = padLeft(26, 6); // "000026"
165
166
// Left padding with custom character
167
const paddedCustom = padLeft("abc", 10, " "); // " abc"
168
169
// Right padding
170
const rightPaddedHex = padRight("0x1a", 8); // "0x1a0000"
171
const rightPaddedString = padRight("hello", 10, "."); // "hello....."
172
173
// Common use case: address padding
174
const address = "0x742E4C5b469F50A4a8b399D4915C1fc93d15651B";
175
const paddedAddress = padLeft(address, 66); // Pad to 32 bytes + "0x"
176
```
177
178
### Two's Complement Operations
179
180
```typescript
181
import { toTwosComplement, fromTwosComplement } from "web3-utils";
182
183
// Convert negative number to two's complement
184
const negative = -123;
185
const twosComp = toTwosComplement(negative); // Two's complement representation
186
const twosCompFixed = toTwosComplement(negative, 8); // Fixed 8-nibble width
187
188
// Convert back from two's complement
189
const original = fromTwosComplement(twosComp); // -123
190
191
// Working with different bit widths
192
const value8bit = toTwosComplement(-1, 2); // 8-bit: "0xff"
193
const value16bit = toTwosComplement(-1, 4); // 16-bit: "0xffff"
194
const value32bit = toTwosComplement(-1, 8); // 32-bit: "0xffffffff"
195
196
// Convert back with same width
197
const decoded8bit = fromTwosComplement(value8bit, 2); // -1
198
const decoded16bit = fromTwosComplement(value16bit, 4); // -1
199
```
200
201
### Object Deep Merge
202
203
```typescript
204
import { mergeDeep } from "web3-utils";
205
206
// Basic object merge
207
const target = { a: 1, b: { x: 10 } };
208
const source1 = { b: { y: 20 }, c: 3 };
209
const source2 = { b: { z: 30 }, d: 4 };
210
211
const merged = mergeDeep(target, source1, source2);
212
// Result: { a: 1, b: { x: 10, y: 20, z: 30 }, c: 3, d: 4 }
213
214
// Configuration merging example
215
const defaultConfig = {
216
network: {
217
chainId: 1,
218
timeout: 5000,
219
retries: 3
220
},
221
logging: {
222
level: 'info',
223
format: 'json'
224
}
225
};
226
227
const userConfig = {
228
network: {
229
timeout: 10000,
230
endpoint: 'https://custom-rpc.com'
231
},
232
logging: {
233
level: 'debug'
234
}
235
};
236
237
const finalConfig = mergeDeep({}, defaultConfig, userConfig);
238
// Result: Merged configuration with user overrides
239
```
240
241
### Uint8Array Operations
242
243
```typescript
244
import { isUint8Array, uint8ArrayConcat, uint8ArrayEquals } from "web3-utils";
245
246
// Type checking
247
const data1 = new Uint8Array([1, 2, 3]);
248
const data2 = Buffer.from([4, 5, 6]); // Node.js Buffer
249
const data3 = [7, 8, 9]; // Regular array
250
251
console.log(isUint8Array(data1)); // true
252
console.log(isUint8Array(data2)); // true (Buffer extends Uint8Array)
253
console.log(isUint8Array(data3)); // false
254
255
// Concatenation
256
const part1 = new Uint8Array([1, 2, 3]);
257
const part2 = new Uint8Array([4, 5, 6]);
258
const part3 = new Uint8Array([7, 8, 9]);
259
260
const combined = uint8ArrayConcat(part1, part2, part3);
261
// Result: Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9])
262
263
// Equality checking
264
const array1 = new Uint8Array([1, 2, 3, 4]);
265
const array2 = new Uint8Array([1, 2, 3, 4]);
266
const array3 = new Uint8Array([1, 2, 3, 5]);
267
268
console.log(uint8ArrayEquals(array1, array2)); // true
269
console.log(uint8ArrayEquals(array1, array3)); // false
270
271
// Common blockchain use case: signature concatenation
272
const r = new Uint8Array(32); // 32 bytes
273
const s = new Uint8Array(32); // 32 bytes
274
const v = new Uint8Array([27]); // 1 byte
275
276
const signature = uint8ArrayConcat(r, s, v); // 65-byte signature
277
```
278
279
### Chunk Response Parser
280
281
```typescript
282
import { ChunkResponseParser, EventEmitter } from "web3-utils";
283
284
// Set up parser for streaming responses
285
const emitter = new EventEmitter();
286
const parser = new ChunkResponseParser(emitter, true);
287
288
// Handle parsed responses
289
emitter.on('message', (response) => {
290
console.log('Parsed response:', response);
291
});
292
293
emitter.on('error', (error) => {
294
console.error('Parser error:', error);
295
});
296
297
// Parse chunked data (e.g., from WebSocket or HTTP streaming)
298
const chunkData = `{"jsonrpc":"2.0","id":1,"result":"0x1"}\n{"jsonrpc":"2.0","id":2,"result":"0x2"}`;
299
const responses = parser.parseResponse(chunkData);
300
301
// responses will contain parsed JSON-RPC objects
302
responses.forEach(response => {
303
console.log('Individual response:', response);
304
});
305
```
306
307
### Advanced Usage Patterns
308
309
```typescript
310
import {
311
padLeft, padRight, mergeDeep, uint8ArrayConcat,
312
toTwosComplement, fromTwosComplement
313
} from "web3-utils";
314
315
// Smart contract data encoding
316
function encodeContractCall(methodId: string, params: Uint8Array[]) {
317
// Method ID is first 4 bytes (8 hex chars + 0x)
318
const paddedMethodId = padRight(methodId, 10, "0");
319
320
// Encode each parameter to 32 bytes
321
const encodedParams = params.map(param => {
322
const hex = Array.from(param, byte => byte.toString(16).padStart(2, '0')).join('');
323
return padLeft(`0x${hex}`, 66, "0"); // 32 bytes = 64 hex chars + "0x"
324
});
325
326
return paddedMethodId + encodedParams.map(p => p.slice(2)).join('');
327
}
328
329
// Configuration system with deep merging
330
class ConfigManager {
331
private config: Record<string, unknown> = {};
332
333
loadDefaults(defaults: Record<string, unknown>) {
334
this.config = mergeDeep({}, defaults);
335
}
336
337
loadUserConfig(userConfig: Record<string, unknown>) {
338
this.config = mergeDeep(this.config, userConfig);
339
}
340
341
loadEnvironmentOverrides(envConfig: Record<string, unknown>) {
342
this.config = mergeDeep(this.config, envConfig);
343
}
344
345
getConfig(): Record<string, unknown> {
346
return this.config;
347
}
348
}
349
350
// Binary data manipulation
351
function processSignature(r: Uint8Array, s: Uint8Array, recovery: number) {
352
// Ensure r and s are 32 bytes
353
const paddedR = r.length < 32 ? uint8ArrayConcat(new Uint8Array(32 - r.length), r) : r;
354
const paddedS = s.length < 32 ? uint8ArrayConcat(new Uint8Array(32 - s.length), s) : s;
355
356
// Recovery value (v) is typically 27 or 28
357
const v = new Uint8Array([recovery + 27]);
358
359
return uint8ArrayConcat(paddedR, paddedS, v);
360
}
361
```