@exodus/bytes 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # `@exodus/bytes`
2
2
 
3
3
  [![](https://flat.badgen.net/npm/v/@exodus/bytes)](https://npmjs.org/package/@exodus/bytes)
4
- ![](https://flat.badgen.net/npm/dm/@exodus/bytes)
4
+ [![](https://flat.badgen.net/github/release/ExodusOSS/bytes?icon=github)](https://github.com/ExodusOSS/bytes/releases)
5
+ [![](https://flat.badgen.net/npm/dm/@exodus/bytes)](https://www.npmcharts.com/compare/@exodus/bytes?minimal=true)
5
6
  [![](https://flat.badgen.net/npm/license/@exodus/bytes)](https://github.com/ExodusOSS/bytes/blob/HEAD/LICENSE)
7
+ [![](https://flat.badgen.net/github/checks/ExodusOSS/bytes/main?icon=github)](https://github.com/ExodusOSS/bytes/actions/workflows/test.yml?query=branch%3Amain)
6
8
 
7
9
  `Uint8Array` conversion to and from `base64`, `base32`, `base58`, `hex`, `utf8`, `utf16`, `bech32` and `wif`
8
10
 
@@ -98,6 +100,8 @@ See [the list of encodings](https://encoding.spec.whatwg.org/#names-and-labels).
98
100
 
99
101
  ### `@exodus/bytes/utf8.js`
100
102
 
103
+ UTF-8 encoding/decoding
104
+
101
105
  ```js
102
106
  import { utf8fromString, utf8toString } from '@exodus/bytes/utf8.js'
103
107
 
@@ -105,13 +109,45 @@ import { utf8fromString, utf8toString } from '@exodus/bytes/utf8.js'
105
109
  import { utf8fromStringLoose, utf8toStringLoose } from '@exodus/bytes/utf8.js'
106
110
  ```
107
111
 
108
- ##### `utf8fromString(str, format = 'uint8')`
109
- ##### `utf8fromStringLoose(str, format = 'uint8')`
110
- ##### `utf8toString(arr)`
111
- ##### `utf8toStringLoose(arr)`
112
+ _These methods by design encode/decode BOM (codepoint `U+FEFF` Byte Order Mark) as-is._\
113
+ _If you need BOM handling or detection, use `@exodus/bytes/encoding.js`_
114
+
115
+ #### `utf8fromString(string, format = 'uint8')`
116
+
117
+ Encode a string to UTF-8 bytes (strict mode)
118
+
119
+ Throws on invalid Unicode (unpaired surrogates)
120
+
121
+ #### `utf8fromStringLoose(string, format = 'uint8')`
122
+
123
+ Encode a string to UTF-8 bytes (loose mode)
124
+
125
+ Replaces invalid Unicode (unpaired surrogates) with replacement codepoints `U+FFFD`
126
+ per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
127
+
128
+ _Such replacement is a non-injective function, is irreversable and causes collisions.\
129
+ Prefer using strict throwing methods for cryptography applications._
130
+
131
+ #### `utf8toString(arr)`
132
+
133
+ Decode UTF-8 bytes to a string (strict mode)
134
+
135
+ Throws on invalid UTF-8 byte sequences
136
+
137
+ #### `utf8toStringLoose(arr)`
138
+
139
+ Decode UTF-8 bytes to a string (loose mode)
140
+
141
+ Replaces invalid UTF-8 byte sequences with replacement codepoints `U+FFFD`
142
+ per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
143
+
144
+ _Such replacement is a non-injective function, is irreversable and causes collisions.\
145
+ Prefer using strict throwing methods for cryptography applications._
112
146
 
113
147
  ### `@exodus/bytes/utf16.js`
114
148
 
149
+ UTF-16 encoding/decoding
150
+
115
151
  ```js
116
152
  import { utf16fromString, utf16toString } from '@exodus/bytes/utf16.js'
117
153
 
@@ -119,17 +155,46 @@ import { utf16fromString, utf16toString } from '@exodus/bytes/utf16.js'
119
155
  import { utf16fromStringLoose, utf16toStringLoose } from '@exodus/bytes/utf16.js'
120
156
  ```
121
157
 
122
- ##### `utf16fromString(str, format = 'uint16')`
123
- ##### `utf16fromStringLoose(str, format = 'uint16')`
124
- ##### `utf16toString(arr, 'uint16')`
125
- ##### `utf16toStringLoose(arr, 'uint16')`
158
+ _These methods by design encode/decode BOM (codepoint `U+FEFF` Byte Order Mark) as-is._\
159
+ _If you need BOM handling or detection, use `@exodus/bytes/encoding.js`_
126
160
 
127
- ### `@exodus/bytes/single-byte.js`
161
+ #### `utf16fromString(string, format = 'uint16')`
128
162
 
129
- ```js
130
- import { createSinglebyteDecoder, createSinglebyteEncoder } from '@exodus/bytes/single-byte.js'
131
- import { windows1252toString, windows1252fromString } from '@exodus/bytes/single-byte.js'
132
- ```
163
+ Encode a string to UTF-16 bytes (strict mode)
164
+
165
+ Throws on invalid Unicode (unpaired surrogates)
166
+
167
+ #### `utf16fromStringLoose(string, format = 'uint16')`
168
+
169
+ Encode a string to UTF-16 bytes (loose mode)
170
+
171
+ Replaces invalid Unicode (unpaired surrogates) with replacement codepoints `U+FFFD`
172
+ per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
173
+
174
+ _Such replacement is a non-injective function, is irreversible and causes collisions.\
175
+ Prefer using strict throwing methods for cryptography applications._
176
+
177
+ #### `utf16toString(arr, format = 'uint16')`
178
+
179
+ Decode UTF-16 bytes to a string (strict mode)
180
+
181
+ Throws on invalid UTF-16 byte sequences
182
+
183
+ Throws on non-even byte length.
184
+
185
+ #### `utf16toStringLoose(arr, format = 'uint16')`
186
+
187
+ Decode UTF-16 bytes to a string (loose mode)
188
+
189
+ Replaces invalid UTF-16 byte sequences with replacement codepoints `U+FFFD`
190
+ per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
191
+
192
+ _Such replacement is a non-injective function, is irreversible and causes collisions.\
193
+ Prefer using strict throwing methods for cryptography applications._
194
+
195
+ Throws on non-even byte length.
196
+
197
+ ### `@exodus/bytes/single-byte.js`
133
198
 
134
199
  Decode / encode the legacy single-byte encodings according to the
135
200
  [Encoding standard](https://encoding.spec.whatwg.org/)
@@ -137,6 +202,12 @@ Decode / encode the legacy single-byte encodings according to the
137
202
  [§14.5](https://encoding.spec.whatwg.org/#x-user-defined)),
138
203
  and [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859) `iso-8859-*` mappings.
139
204
 
205
+ ```js
206
+ import { createSinglebyteDecoder, createSinglebyteEncoder } from '@exodus/bytes/single-byte.js'
207
+ import { windows1252toString, windows1252fromString } from '@exodus/bytes/single-byte.js'
208
+ import { latin1toString, latin1fromString } from '@exodus/bytes/single-byte.js'
209
+ ```
210
+
140
211
  Supports all single-byte encodings listed in the WHATWG Encoding standard:
141
212
  `ibm866`, `iso-8859-2`, `iso-8859-3`, `iso-8859-4`, `iso-8859-5`, `iso-8859-6`, `iso-8859-7`, `iso-8859-8`,
142
213
  `iso-8859-8-i`, `iso-8859-10`, `iso-8859-13`, `iso-8859-14`, `iso-8859-15`, `iso-8859-16`, `koi8-r`, `koi8-u`,
@@ -167,13 +238,18 @@ Also supports `iso-8859-1`, `iso-8859-9`, `iso-8859-11` as defined at
167
238
  '\x80\x81Ğ' // this is iso-8859-9 as defined at https://unicode.org/Public/MAPPINGS/ISO8859/8859-9.txt
168
239
  ```
169
240
 
170
- ##### `createSinglebyteDecoder(encoding, loose = false)`
241
+ All WHATWG Encoding spec [`windows-*` encodings](https://encoding.spec.whatwg.org/#windows-874) are supersets of
242
+ corresponding [unicode.org encodings](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/), meaning that
243
+ they encode/decode all the old valid (non-replacement) strings / byte sequences identically, but can also support
244
+ a wider range of inputs.
245
+
246
+ #### `createSinglebyteDecoder(encoding, loose = false)`
171
247
 
172
248
  Create a decoder for a supported one-byte `encoding`, given its lowercased name `encoding`.
173
249
 
174
250
  Returns a function `decode(arr)` that decodes bytes to a string.
175
251
 
176
- ##### `createSinglebyteEncoder(encoding, { mode = 'fatal' })`
252
+ #### `createSinglebyteEncoder(encoding, { mode = 'fatal' })`
177
253
 
178
254
  Create an encoder for a supported one-byte `encoding`, given its lowercased name `encoding`.
179
255
 
@@ -182,7 +258,7 @@ Returns a function `encode(string)` that encodes a string to bytes.
182
258
  In `'fatal'` mode (default), will throw on non well-formed strings or any codepoints which could
183
259
  not be encoded in the target encoding.
184
260
 
185
- ##### `latin1toString(arr)`
261
+ #### `latin1toString(arr)`
186
262
 
187
263
  Decode `iso-8859-1` bytes to a string.
188
264
 
@@ -196,18 +272,18 @@ const latin1toString = createSinglebyteDecoder('iso-8859-1')
196
272
  Note: this is different from `new TextDecoder('iso-8859-1')` and `new TextDecoder('latin1')`, as
197
273
  those alias to `new TextDecoder('windows-1252')`.
198
274
 
199
- ##### `latin1fromString(string)`
275
+ #### `latin1fromString(string)`
200
276
 
201
277
  Encode a string to `iso-8859-1` bytes.
202
278
 
203
- Will throw on non well-formed strings or any codepoints which could not be encoded in `iso-8859-1`.
279
+ Throws on non well-formed strings or any codepoints which could not be encoded in `iso-8859-1`.
204
280
 
205
281
  Same as:
206
282
  ```js
207
283
  const latin1fromString = createSinglebyteEncoder('iso-8859-1', { mode: 'fatal' })
208
284
  ```
209
285
 
210
- ##### `windows1252toString(arr)`
286
+ #### `windows1252toString(arr)`
211
287
 
212
288
  Decode `windows-1252` bytes to a string.
213
289
 
@@ -218,11 +294,11 @@ Same as:
218
294
  const windows1252toString = createSinglebyteDecoder('windows-1252')
219
295
  ```
220
296
 
221
- ##### `windows1252fromString(string)`
297
+ #### `windows1252fromString(string)`
222
298
 
223
299
  Encode a string to `windows-1252` bytes.
224
300
 
225
- Will throw on non well-formed strings or any codepoints which could not be encoded in `windows-1252`.
301
+ Throws on non well-formed strings or any codepoints which could not be encoded in `windows-1252`.
226
302
 
227
303
  Same as:
228
304
  ```js
@@ -231,50 +307,84 @@ const windows1252fromString = createSinglebyteEncoder('windows-1252', { mode: 'f
231
307
 
232
308
  ### `@exodus/bytes/multi-byte.js`
233
309
 
234
- ```js
235
- import { createMultibyteDecoder } from '@exodus/bytes/multi-byte.js'
236
- ```
237
-
238
- Decode the legacy multi-byte encodings according to the [Encoding standard](https://encoding.spec.whatwg.org/)
310
+ Decode / encode the legacy multi-byte encodings according to the
311
+ [Encoding standard](https://encoding.spec.whatwg.org/)
239
312
  ([§10](https://encoding.spec.whatwg.org/#legacy-multi-byte-chinese-(simplified)-encodings),
240
313
  [§11](https://encoding.spec.whatwg.org/#legacy-multi-byte-chinese-(traditional)-encodings),
241
314
  [§12](https://encoding.spec.whatwg.org/#legacy-multi-byte-japanese-encodings),
242
315
  [§13](https://encoding.spec.whatwg.org/#legacy-multi-byte-korean-encodings)).
243
316
 
244
- Supports all legacy multi-byte encodings listed in the standard:
317
+ ```js
318
+ import { createMultibyteDecoder, createMultibyteEncoder } from '@exodus/bytes/multi-byte.js'
319
+ ```
320
+
321
+ Supports all legacy multi-byte encodings listed in the WHATWG Encoding standard:
245
322
  `gbk`, `gb18030`, `big5`, `euc-jp`, `iso-2022-jp`, `shift_jis`, `euc-kr`.
246
323
 
247
- ##### `createMultibyteDecoder(encoding, loose = false)`
324
+ #### `createMultibyteDecoder(encoding, loose = false)`
248
325
 
249
326
  Create a decoder for a supported legacy multi-byte `encoding`, given its lowercased name `encoding`.
250
327
 
251
328
  Returns a function `decode(arr, stream = false)` that decodes bytes to a string.
252
329
 
253
- That function will have state while `stream = true` is used.
330
+ The returned function will maintain internal state while `stream = true` is used, allowing it to
331
+ handle incomplete multi-byte sequences across multiple calls.
332
+ State is reset when `stream = false` or when the function is called without the `stream` parameter.
333
+
334
+ #### `createMultibyteEncoder(encoding, { mode = 'fatal' })`
335
+
336
+ Create an encoder for a supported legacy multi-byte `encoding`, given its lowercased name `encoding`.
337
+
338
+ Returns a function `encode(string)` that encodes a string to bytes.
339
+
340
+ In `'fatal'` mode (default), will throw on non well-formed strings or any codepoints which could
341
+ not be encoded in the target encoding.
254
342
 
255
343
  ### `@exodus/bytes/bigint.js`
256
344
 
345
+ Convert between BigInt and Uint8Array
346
+
257
347
  ```js
258
348
  import { fromBigInt, toBigInt } from '@exodus/bytes/bigint.js'
259
349
  ```
260
350
 
261
- ##### `fromBigInt(bigint, { length, format = 'uint8' })`
262
- ##### `toBigInt(arr)`
351
+ #### `fromBigInt(bigint, { length, format = 'uint8' })`
352
+
353
+ Convert a BigInt to a Uint8Array or Buffer
354
+
355
+ The output bytes are in big-endian format.
356
+
357
+ Throws if the BigInt is negative or cannot fit into the specified length.
358
+
359
+ #### `toBigInt(arr)`
360
+
361
+ Convert a Uint8Array or Buffer to a BigInt
362
+
363
+ The bytes are interpreted as a big-endian unsigned integer.
263
364
 
264
365
  ### `@exodus/bytes/hex.js`
265
366
 
266
- Implements Base16 from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648) (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
367
+ Implements Base16 from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
368
+ (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
267
369
 
268
370
  ```js
269
371
  import { fromHex, toHex } from '@exodus/bytes/hex.js'
270
372
  ```
271
373
 
272
- ##### `fromHex(string)`
273
- ##### `toHex(arr)`
374
+ #### `fromHex(string, format = 'uint8')`
375
+
376
+ Decode a hex string to bytes
377
+
378
+ Unlike `Buffer.from()`, throws on invalid input
379
+
380
+ #### `toHex(arr)`
381
+
382
+ Encode a `Uint8Array` to a lowercase hex string
274
383
 
275
384
  ### `@exodus/bytes/base64.js`
276
385
 
277
- Implements Base64 from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648) (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
386
+ Implements base64 and base64url from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
387
+ (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
278
388
 
279
389
  ```js
280
390
  import { fromBase64, toBase64 } from '@exodus/bytes/base64.js'
@@ -282,116 +392,259 @@ import { fromBase64url, toBase64url } from '@exodus/bytes/base64.js'
282
392
  import { fromBase64any } from '@exodus/bytes/base64.js'
283
393
  ```
284
394
 
285
- ##### `fromBase64(str, { format = 'uint8', padding = 'both' })`
286
- ##### `fromBase64url(str, { format = 'uint8', padding = false })`
287
- ##### `fromBase64any(str, { format = 'uint8', padding = 'both' })`
288
- ##### `toBase64(arr, { padding = true })`
289
- ##### `toBase64url(arr, { padding = false })`
395
+ #### `fromBase64(string, { format = 'uint8', padding = 'both' })`
396
+
397
+ Decode a base64 string to bytes
398
+
399
+ Operates in strict mode for last chunk, does not allow whitespace
400
+
401
+ #### `fromBase64url(string, { format = 'uint8', padding = false })`
402
+
403
+ Decode a base64url string to bytes
404
+
405
+ Operates in strict mode for last chunk, does not allow whitespace
406
+
407
+ #### `fromBase64any(string, { format = 'uint8', padding = 'both' })`
408
+
409
+ Decode either base64 or base64url string to bytes
410
+
411
+ Automatically detects the variant based on characters present
412
+
413
+ #### `toBase64(arr, { padding = true })`
414
+
415
+ Encode a `Uint8Array` to a base64 string (RFC 4648)
416
+
417
+ #### `toBase64url(arr, { padding = false })`
418
+
419
+ Encode a `Uint8Array` to a base64url string (RFC 4648)
290
420
 
291
421
  ### `@exodus/bytes/base32.js`
292
422
 
293
- Implements Base32 from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648) (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
423
+ Implements base32 and base32hex from [RFC4648](https://datatracker.ietf.org/doc/html/rfc4648)
424
+ (no differences from [RFC3548](https://datatracker.ietf.org/doc/html/rfc4648)).
294
425
 
295
426
  ```js
296
427
  import { fromBase32, toBase32 } from '@exodus/bytes/base32.js'
297
428
  import { fromBase32hex, toBase32hex } from '@exodus/bytes/base32.js'
298
429
  ```
299
430
 
300
- ##### `fromBase32(str, { format = 'uint8', padding = 'both' })`
301
- ##### `fromBase32hex(str, { format = 'uint8', padding = 'both' })`
302
- ##### `toBase32(arr, { padding = false })`
303
- ##### `toBase32hex(arr, { padding = false })`
431
+ #### `fromBase32(string, { format = 'uint8', padding = 'both' })`
432
+
433
+ Decode a base32 string to bytes
434
+
435
+ Operates in strict mode for last chunk, does not allow whitespace
436
+
437
+ #### `fromBase32hex(string, { format = 'uint8', padding = 'both' })`
438
+
439
+ Decode a base32hex string to bytes
440
+
441
+ Operates in strict mode for last chunk, does not allow whitespace
442
+
443
+ #### `toBase32(arr, { padding = false })`
444
+
445
+ Encode a `Uint8Array` to a base32 string (RFC 4648)
446
+
447
+ #### `toBase32hex(arr, { padding = false })`
448
+
449
+ Encode a `Uint8Array` to a base32hex string (RFC 4648)
304
450
 
305
451
  ### `@exodus/bytes/bech32.js`
306
452
 
307
- Implements [BIP-0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#specification) and [BIP-0350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki#specification).
453
+ Implements bech32 and bech32m from
454
+ [BIP-0173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#specification)
455
+ and [BIP-0350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki#specification).
308
456
 
309
457
  ```js
310
458
  import { fromBech32, toBech32 } from '@exodus/bytes/bech32.js'
311
- import { fromBech32m, toBech32m } from '@exodus/bytes/base32.js'
312
- import { getPrefix } from '@exodus/bytes/base32.js'
459
+ import { fromBech32m, toBech32m } from '@exodus/bytes/bech32.js'
460
+ import { getPrefix } from '@exodus/bytes/bech32.js'
313
461
  ```
314
462
 
315
- ##### `getPrefix(str, limit = 90)`
463
+ #### `getPrefix(string, limit = 90)`
464
+
465
+ Extract the prefix from a bech32 or bech32m string without full validation
466
+
467
+ This is a quick check that skips most validation.
316
468
 
317
- ##### `fromBech32(str, limit = 90)`
318
- ##### `toBech32(prefix, bytes, limit = 90)`
469
+ #### `fromBech32(string, limit = 90)`
319
470
 
320
- ##### `fromBech32m(str, limit = 90)`
321
- ##### `toBech32m(prefix, bytes, limit = 90)`
471
+ Decode a bech32 string to bytes
472
+
473
+ #### `toBech32(prefix, bytes, limit = 90)`
474
+
475
+ Encode bytes to a bech32 string
476
+
477
+ #### `fromBech32m(string, limit = 90)`
478
+
479
+ Decode a bech32m string to bytes
480
+
481
+ #### `toBech32m(prefix, bytes, limit = 90)`
482
+
483
+ Encode bytes to a bech32m string
322
484
 
323
485
  ### `@exodus/bytes/base58.js`
324
486
 
487
+ Implements [base58](https://www.ietf.org/archive/id/draft-msporny-base58-03.txt) encoding.
488
+
489
+ Supports both standard base58 and XRP variant alphabets.
490
+
325
491
  ```js
326
492
  import { fromBase58, toBase58 } from '@exodus/bytes/base58.js'
327
493
  import { fromBase58xrp, toBase58xrp } from '@exodus/bytes/base58.js'
328
494
  ```
329
495
 
330
- ##### `fromBase58(str, format = 'uint8')`
331
- ##### `toBase58(arr)`
496
+ #### `fromBase58(string, format = 'uint8')`
497
+
498
+ Decode a base58 string to bytes
499
+
500
+ Uses the standard Bitcoin base58 alphabet
501
+
502
+ #### `toBase58(arr)`
503
+
504
+ Encode a `Uint8Array` to a base58 string
332
505
 
333
- ##### `fromBase58xrp(str, format = 'uint8')`
334
- ##### `toBase58xrp(arr)`
506
+ Uses the standard Bitcoin base58 alphabet
507
+
508
+ #### `fromBase58xrp(string, format = 'uint8')`
509
+
510
+ Decode a base58 string to bytes using XRP alphabet
511
+
512
+ Uses the XRP variant base58 alphabet
513
+
514
+ #### `toBase58xrp(arr)`
515
+
516
+ Encode a `Uint8Array` to a base58 string using XRP alphabet
517
+
518
+ Uses the XRP variant base58 alphabet
335
519
 
336
520
  ### `@exodus/bytes/base58check.js`
337
521
 
522
+ Implements [base58check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoding.
523
+
338
524
  ```js
339
525
  import { fromBase58check, toBase58check } from '@exodus/bytes/base58check.js'
340
526
  import { fromBase58checkSync, toBase58checkSync } from '@exodus/bytes/base58check.js'
341
527
  import { makeBase58check } from '@exodus/bytes/base58check.js'
342
528
  ```
343
529
 
344
- On non-Node.js, requires peer dependency [@exodus/crypto](https://www.npmjs.com/package/@exodus/crypto) to be installed.
530
+ On non-Node.js, requires peer dependency [@noble/hashes](https://www.npmjs.com/package/@noble/hashes) to be installed.
531
+
532
+ #### `async fromBase58check(string, format = 'uint8')`
533
+
534
+ Decode a base58check string to bytes asynchronously
535
+
536
+ Validates the checksum using double SHA-256
537
+
538
+ #### `async toBase58check(arr)`
345
539
 
346
- ##### `async fromBase58check(str, format = 'uint8')`
347
- ##### `async toBase58check(arr)`
348
- ##### `fromBase58checkSync(str, format = 'uint8')`
349
- ##### `toBase58checkSync(arr)`
350
- ##### `makeBase58check(hashAlgo, hashAlgoSync)`
540
+ Encode bytes to base58check string asynchronously
541
+
542
+ Uses double SHA-256 for checksum calculation
543
+
544
+ #### `fromBase58checkSync(string, format = 'uint8')`
545
+
546
+ Decode a base58check string to bytes synchronously
547
+
548
+ Validates the checksum using double SHA-256
549
+
550
+ #### `toBase58checkSync(arr)`
551
+
552
+ Encode bytes to base58check string synchronously
553
+
554
+ Uses double SHA-256 for checksum calculation
555
+
556
+ #### `makeBase58check(hashAlgo, hashAlgoSync)`
557
+
558
+ Create a base58check encoder/decoder with custom hash functions
351
559
 
352
560
  ### `@exodus/bytes/wif.js`
353
561
 
562
+ Wallet Import Format (WIF) encoding and decoding.
563
+
354
564
  ```js
355
565
  import { fromWifString, toWifString } from '@exodus/bytes/wif.js'
356
566
  import { fromWifStringSync, toWifStringSync } from '@exodus/bytes/wif.js'
357
567
  ```
358
568
 
359
- On non-Node.js, requires peer dependency [@exodus/crypto](https://www.npmjs.com/package/@exodus/crypto) to be installed.
569
+ On non-Node.js, requires peer dependency [@noble/hashes](https://www.npmjs.com/package/@noble/hashes) to be installed.
360
570
 
361
- ##### `async fromWifString(string, version)`
362
- ##### `fromWifStringSync(string, version)`
363
- ##### `async toWifString({ version, privateKey, compressed })`
364
- ##### `toWifStringSync({ version, privateKey, compressed })`
571
+ #### `async fromWifString(string[, version])`
365
572
 
366
- ### `@exodus/bytes/encoding.js`
573
+ Decode a WIF string to WIF data
367
574
 
368
- ```js
369
- import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding.js'
370
- import { TextDecoderStream, TextEncoderStream } from '@exodus/bytes/encoding.js' // Requires Streams
575
+ Returns a promise that resolves to an object with `{ version, privateKey, compressed }`.
371
576
 
372
- // Hooks for standards
373
- import { getBOMEncoding, legacyHookDecode, labelToName, normalizeEncoding } from '@exodus/bytes/encoding.js'
577
+ The optional `version` parameter validates the version byte.
578
+
579
+ Throws if the WIF string is invalid or version doesn't match.
580
+
581
+ #### `fromWifStringSync(string[, version])`
582
+
583
+ Decode a WIF string to WIF data (synchronous)
584
+
585
+ Returns an object with `{ version, privateKey, compressed }`.
586
+
587
+ The optional `version` parameter validates the version byte.
588
+
589
+ Throws if the WIF string is invalid or version doesn't match.
590
+
591
+ #### `async toWifString({ version, privateKey, compressed })`
592
+
593
+ Encode WIF data to a WIF string
594
+
595
+ #### `toWifStringSync({ version, privateKey, compressed })`
596
+
597
+ Encode WIF data to a WIF string (synchronous)
598
+
599
+ ### `@exodus/bytes/array.js`
600
+
601
+ TypedArray utils and conversions.
602
+
603
+ ```js
604
+ import { typedView } from '@exodus/bytes/array.js'
374
605
  ```
375
606
 
607
+ #### `typedView(arr, format = 'uint8')`
608
+
609
+ Create a view of a TypedArray in the specified format (`'uint8'` or `'buffer'`)
610
+
611
+ Important: does not copy data, returns a view on the same underlying buffer
612
+
613
+ ### `@exodus/bytes/encoding.js`
614
+
376
615
  Implements the [Encoding standard](https://encoding.spec.whatwg.org/):
377
616
  [TextDecoder](https://encoding.spec.whatwg.org/#interface-textdecoder),
378
617
  [TextEncoder](https://encoding.spec.whatwg.org/#interface-textencoder),
379
618
  [TextDecoderStream](https://encoding.spec.whatwg.org/#interface-textdecoderstream),
380
619
  [TextEncoderStream](https://encoding.spec.whatwg.org/#interface-textencoderstream),
381
- some [hooks](https://encoding.spec.whatwg.org/#specification-hooks) (see below).
620
+ some [hooks](https://encoding.spec.whatwg.org/#specification-hooks).
621
+
622
+ ```js
623
+ import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding.js'
624
+ import { TextDecoderStream, TextEncoderStream } from '@exodus/bytes/encoding.js' // Requires Streams
625
+
626
+ // Hooks for standards
627
+ import { getBOMEncoding, legacyHookDecode, labelToName, normalizeEncoding } from '@exodus/bytes/encoding.js'
628
+ ```
382
629
 
383
630
  #### `new TextDecoder(label = 'utf-8', { fatal = false, ignoreBOM = false })`
384
631
 
385
632
  [TextDecoder](https://encoding.spec.whatwg.org/#interface-textdecoder) implementation/polyfill.
386
633
 
634
+ Decode bytes to strings according to [WHATWG Encoding](https://encoding.spec.whatwg.org) specification.
635
+
387
636
  #### `new TextEncoder()`
388
637
 
389
638
  [TextEncoder](https://encoding.spec.whatwg.org/#interface-textencoder) implementation/polyfill.
390
639
 
640
+ Encode strings to UTF-8 bytes according to [WHATWG Encoding](https://encoding.spec.whatwg.org) specification.
641
+
391
642
  #### `new TextDecoderStream(label = 'utf-8', { fatal = false, ignoreBOM = false })`
392
643
 
393
644
  [TextDecoderStream](https://encoding.spec.whatwg.org/#interface-textdecoderstream) implementation/polyfill.
394
645
 
646
+ A [Streams](https://streams.spec.whatwg.org/) wrapper for `TextDecoder`.
647
+
395
648
  Requires [Streams](https://streams.spec.whatwg.org/) to be either supported by the platform or
396
649
  [polyfilled](https://npmjs.com/package/web-streams-polyfill).
397
650
 
@@ -399,6 +652,8 @@ Requires [Streams](https://streams.spec.whatwg.org/) to be either supported by t
399
652
 
400
653
  [TextEncoderStream](https://encoding.spec.whatwg.org/#interface-textencoderstream) implementation/polyfill.
401
654
 
655
+ A [Streams](https://streams.spec.whatwg.org/) wrapper for `TextEncoder`.
656
+
402
657
  Requires [Streams](https://streams.spec.whatwg.org/) to be either supported by the platform or
403
658
  [polyfilled](https://npmjs.com/package/web-streams-polyfill).
404
659
 
@@ -406,7 +661,7 @@ Requires [Streams](https://streams.spec.whatwg.org/) to be either supported by t
406
661
 
407
662
  Implements [get an encoding from a string `label`](https://encoding.spec.whatwg.org/#concept-encoding-get).
408
663
 
409
- Converts an encoding [label](https://encoding.spec.whatwg.org/#names-and-labels) to its name,
664
+ Convert an encoding [label](https://encoding.spec.whatwg.org/#names-and-labels) to its name,
410
665
  as a case-sensitive string.
411
666
 
412
667
  If an encoding with that label does not exist, returns `null`.
@@ -415,7 +670,7 @@ All encoding names are also valid labels for corresponding encodings.
415
670
 
416
671
  #### `normalizeEncoding(label)`
417
672
 
418
- Converts an encoding [label](https://encoding.spec.whatwg.org/#names-and-labels) to its name,
673
+ Convert an encoding [label](https://encoding.spec.whatwg.org/#names-and-labels) to its name,
419
674
  as an ASCII-lowercased string.
420
675
 
421
676
  If an encoding with that label does not exist, returns `null`.
@@ -438,10 +693,10 @@ All encoding names are also valid labels for corresponding encodings.
438
693
  Implements [BOM sniff](https://encoding.spec.whatwg.org/#bom-sniff) legacy hook.
439
694
 
440
695
  Given a `TypedArray` or an `ArrayBuffer` instance `input`, returns either of:
441
- * `'utf-8'`, if `input` starts with UTF-8 byte order mark.
442
- * `'utf-16le'`, if `input` starts with UTF-16LE byte order mark.
443
- * `'utf-16be'`, if `input` starts with UTF-16BE byte order mark.
444
- * `null` otherwise.
696
+ - `'utf-8'`, if `input` starts with UTF-8 byte order mark.
697
+ - `'utf-16le'`, if `input` starts with UTF-16LE byte order mark.
698
+ - `'utf-16be'`, if `input` starts with UTF-16BE byte order mark.
699
+ - `null` otherwise.
445
700
 
446
701
  #### `legacyHookDecode(input, fallbackEncoding = 'utf-8')`
447
702
 
@@ -454,10 +709,10 @@ decodes the `input` using that encoding, skipping BOM if it was present.
454
709
 
455
710
  Notes:
456
711
 
457
- * BOM-sniffed encoding takes precedence over `fallbackEncoding` option per spec.
458
- Use with care.
459
- * Always operates in non-fatal [mode](https://encoding.spec.whatwg.org/#textdecoder-error-mode),
460
- aka replacement. It can convert different byte sequences to equal strings.
712
+ - BOM-sniffed encoding takes precedence over `fallbackEncoding` option per spec.
713
+ Use with care.
714
+ - Always operates in non-fatal [mode](https://encoding.spec.whatwg.org/#textdecoder-error-mode),
715
+ aka replacement. It can convert different byte sequences to equal strings.
461
716
 
462
717
  This method is similar to the following code, except that it doesn't support encoding labels and
463
718
  only expects lowercased encoding name:
@@ -468,6 +723,10 @@ new TextDecoder(getBOMEncoding(input) ?? fallbackEncoding).decode(input)
468
723
 
469
724
  ### `@exodus/bytes/encoding-lite.js`
470
725
 
726
+ The exact same exports as `@exodus/bytes/encoding.js` are also exported as
727
+ `@exodus/bytes/encoding-lite.js`, with the difference that the lite version does not load
728
+ multi-byte `TextDecoder` encodings by default to reduce bundle size 10x.
729
+
471
730
  ```js
472
731
  import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding-lite.js'
473
732
  import { TextDecoderStream, TextEncoderStream } from '@exodus/bytes/encoding-lite.js' // Requires Streams
@@ -476,10 +735,6 @@ import { TextDecoderStream, TextEncoderStream } from '@exodus/bytes/encoding-lit
476
735
  import { getBOMEncoding, legacyHookDecode, labelToName, normalizeEncoding } from '@exodus/bytes/encoding-lite.js'
477
736
  ```
478
737
 
479
- The exact same exports as `@exodus/bytes/encoding.js` are also exported as
480
- `@exodus/bytes/encoding-lite.js`, with the difference that the lite version does not load
481
- multi-byte `TextDecoder` encodings by default to reduce bundle size 10x.
482
-
483
738
  The only affected encodings are: `gbk`, `gb18030`, `big5`, `euc-jp`, `iso-2022-jp`, `shift_jis`
484
739
  and their [labels](https://encoding.spec.whatwg.org/#names-and-labels) when used with `TextDecoder`.
485
740
 
@@ -525,6 +780,31 @@ true
525
780
  '%'
526
781
  ```
527
782
 
783
+ ### `@exodus/bytes/encoding-browser.js`
784
+
785
+ Same as `@exodus/bytes/encoding.js`, but in browsers instead of polyfilling just uses whatever the
786
+ browser provides, drastically reducing the bundle size (to less than 2 KiB gzipped).
787
+
788
+ ```js
789
+ import { TextDecoder, TextEncoder } from '@exodus/bytes/encoding-browser.js'
790
+ import { TextDecoderStream, TextEncoderStream } from '@exodus/bytes/encoding-browser.js' // Requires Streams
791
+
792
+ // Hooks for standards
793
+ import { getBOMEncoding, legacyHookDecode, labelToName, normalizeEncoding } from '@exodus/bytes/encoding-browser.js'
794
+ ```
795
+
796
+ Under non-browser engines (Node.js, React Native, etc.) a full polyfill is used as those platforms
797
+ do not provide sufficiently complete / non-buggy `TextDecoder` APIs.
798
+
799
+ > [!NOTE]
800
+ > Implementations in browsers [have bugs](https://docs.google.com/spreadsheets/d/1pdEefRG6r9fZy61WHGz0TKSt8cO4ISWqlpBN5KntIvQ/edit),
801
+ > but they are fixing them and the expected update window is short.\
802
+ > If you want to circumvent browser bugs, use full `@exodus/bytes/encoding.js` import.
803
+
804
+ ## Changelog
805
+
806
+ See [GitHub Releases](https://github.com/ExodusOSS/bytes/releases) tab
807
+
528
808
  ## License
529
809
 
530
810
  [MIT](./LICENSE)