@exodus/bytes 1.9.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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Decode / encode the legacy multi-byte encodings according to the
3
+ * [Encoding standard](https://encoding.spec.whatwg.org/)
4
+ * ([§10](https://encoding.spec.whatwg.org/#legacy-multi-byte-chinese-(simplified)-encodings),
5
+ * [§11](https://encoding.spec.whatwg.org/#legacy-multi-byte-chinese-(traditional)-encodings),
6
+ * [§12](https://encoding.spec.whatwg.org/#legacy-multi-byte-japanese-encodings),
7
+ * [§13](https://encoding.spec.whatwg.org/#legacy-multi-byte-korean-encodings)).
8
+ *
9
+ * ```js
10
+ * import { createMultibyteDecoder, createMultibyteEncoder } from '@exodus/bytes/multi-byte.js'
11
+ * ```
12
+ *
13
+ * Supports all legacy multi-byte encodings listed in the WHATWG Encoding standard:
14
+ * `gbk`, `gb18030`, `big5`, `euc-jp`, `iso-2022-jp`, `shift_jis`, `euc-kr`.
15
+ *
16
+ * @module @exodus/bytes/multi-byte.js
17
+ */
18
+
19
+ /// <reference types="node" />
20
+
21
+ import type { Uint8ArrayBuffer } from './array.js';
22
+
23
+ /**
24
+ * Create a decoder for a supported legacy multi-byte `encoding`, given its lowercased name `encoding`.
25
+ *
26
+ * Returns a function `decode(arr, stream = false)` that decodes bytes to a string.
27
+ *
28
+ * The returned function will maintain internal state while `stream = true` is used, allowing it to
29
+ * handle incomplete multi-byte sequences across multiple calls.
30
+ * State is reset when `stream = false` or when the function is called without the `stream` parameter.
31
+ *
32
+ * @param encoding - The encoding name (e.g., 'gbk', 'gb18030', 'big5', 'euc-jp', 'iso-2022-jp', 'shift_jis', 'euc-kr')
33
+ * @param loose - If true, replaces unmapped bytes with replacement character instead of throwing (default: false)
34
+ * @returns A function that decodes bytes to string, with optional streaming support
35
+ */
36
+ export function createMultibyteDecoder(
37
+ encoding: string,
38
+ loose?: boolean
39
+ ): (arr: Uint8Array, stream?: boolean) => string;
40
+
41
+ /**
42
+ * Create an encoder for a supported legacy multi-byte `encoding`, given its lowercased name `encoding`.
43
+ *
44
+ * Returns a function `encode(string)` that encodes a string to bytes.
45
+ *
46
+ * In `'fatal'` mode (default), will throw on non well-formed strings or any codepoints which could
47
+ * not be encoded in the target encoding.
48
+ *
49
+ * @param encoding - The encoding name (e.g., 'gbk', 'gb18030', 'big5', 'euc-jp', 'iso-2022-jp', 'shift_jis', 'euc-kr')
50
+ * @param options - Encoding options
51
+ * @param options.mode - Encoding mode (default: 'fatal'). Currently, only 'fatal' mode is supported.
52
+ * @returns A function that encodes string to bytes
53
+ */
54
+ export function createMultibyteEncoder(
55
+ encoding: string,
56
+ options?: { mode?: 'fatal' }
57
+ ): (string: string) => Uint8ArrayBuffer;
package/package.json CHANGED
@@ -1,7 +1,23 @@
1
1
  {
2
2
  "name": "@exodus/bytes",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Various operations on Uint8Array data",
5
+ "keywords": [
6
+ "encoding",
7
+ "uint8array",
8
+ "textdecoder",
9
+ "textencoder",
10
+ "utf8",
11
+ "utf16",
12
+ "hex",
13
+ "base64",
14
+ "base32",
15
+ "base58",
16
+ "base58check",
17
+ "bech32",
18
+ "bech32m",
19
+ "wif"
20
+ ],
5
21
  "scripts": {
6
22
  "lint": "eslint .",
7
23
  "test:javascriptcore": "npm run test:jsc --",
@@ -38,7 +54,7 @@
38
54
  "bugs": {
39
55
  "url": "https://github.com/ExodusOSS/bytes/issues"
40
56
  },
41
- "homepage": "https://github.com/ExodusOSS/bytes#readme",
57
+ "homepage": "https://github.com/ExodusOSS/bytes",
42
58
  "engines": {
43
59
  "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
44
60
  },
@@ -66,13 +82,18 @@
66
82
  "/array.d.ts",
67
83
  "/assert.js",
68
84
  "/base32.js",
85
+ "/base32.d.ts",
69
86
  "/base58.js",
87
+ "/base58.d.ts",
70
88
  "/base58check.js",
89
+ "/base58check.d.ts",
71
90
  "/base58check.node.js",
72
91
  "/base64.js",
73
92
  "/base64.d.ts",
74
93
  "/bech32.js",
94
+ "/bech32.d.ts",
75
95
  "/bigint.js",
96
+ "/bigint.d.ts",
76
97
  "/encoding-browser.js",
77
98
  "/encoding-browser.browser.js",
78
99
  "/encoding-browser.native.js",
@@ -87,15 +108,19 @@
87
108
  "/index.js",
88
109
  "/index.d.ts",
89
110
  "/multi-byte.js",
111
+ "/multi-byte.d.ts",
90
112
  "/multi-byte.node.js",
91
113
  "/single-byte.js",
114
+ "/single-byte.d.ts",
92
115
  "/single-byte.node.js",
93
116
  "/utf16.js",
117
+ "/utf16.d.ts",
94
118
  "/utf16.node.js",
95
119
  "/utf8.js",
96
120
  "/utf8.d.ts",
97
121
  "/utf8.node.js",
98
- "/wif.js"
122
+ "/wif.js",
123
+ "/wif.d.ts"
99
124
  ],
100
125
  "main": "index.js",
101
126
  "module": "index.js",
@@ -109,9 +134,16 @@
109
134
  "types": "./array.d.ts",
110
135
  "default": "./array.js"
111
136
  },
112
- "./base32.js": "./base32.js",
113
- "./base58.js": "./base58.js",
137
+ "./base32.js": {
138
+ "types": "./base32.d.ts",
139
+ "default": "./base32.js"
140
+ },
141
+ "./base58.js": {
142
+ "types": "./base58.d.ts",
143
+ "default": "./base58.js"
144
+ },
114
145
  "./base58check.js": {
146
+ "types": "./base58check.d.ts",
115
147
  "node": "./base58check.node.js",
116
148
  "default": "./base58check.js"
117
149
  },
@@ -119,18 +151,26 @@
119
151
  "types": "./base64.d.ts",
120
152
  "default": "./base64.js"
121
153
  },
122
- "./bech32.js": "./bech32.js",
123
- "./bigint.js": "./bigint.js",
154
+ "./bech32.js": {
155
+ "types": "./bech32.d.ts",
156
+ "default": "./bech32.js"
157
+ },
158
+ "./bigint.js": {
159
+ "types": "./bigint.d.ts",
160
+ "default": "./bigint.js"
161
+ },
124
162
  "./hex.js": {
125
163
  "types": "./hex.d.ts",
126
164
  "node": "./hex.node.js",
127
165
  "default": "./hex.js"
128
166
  },
129
167
  "./multi-byte.js": {
168
+ "types": "./multi-byte.d.ts",
130
169
  "node": "./multi-byte.node.js",
131
170
  "default": "./multi-byte.js"
132
171
  },
133
172
  "./single-byte.js": {
173
+ "types": "./single-byte.d.ts",
134
174
  "node": "./single-byte.node.js",
135
175
  "default": "./single-byte.js"
136
176
  },
@@ -150,6 +190,7 @@
150
190
  "default": "./encoding-browser.js"
151
191
  },
152
192
  "./utf16.js": {
193
+ "types": "./utf16.d.ts",
153
194
  "node": "./utf16.node.js",
154
195
  "default": "./utf16.js"
155
196
  },
@@ -158,7 +199,10 @@
158
199
  "node": "./utf8.node.js",
159
200
  "default": "./utf8.js"
160
201
  },
161
- "./wif.js": "./wif.js"
202
+ "./wif.js": {
203
+ "types": "./wif.d.ts",
204
+ "default": "./wif.js"
205
+ }
162
206
  },
163
207
  "react-native": {
164
208
  "./encoding-browser.js": "./encoding-browser.native.js"
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Decode / encode the legacy single-byte encodings according to the
3
+ * [Encoding standard](https://encoding.spec.whatwg.org/)
4
+ * ([§9](https://encoding.spec.whatwg.org/#legacy-single-byte-encodings),
5
+ * [§14.5](https://encoding.spec.whatwg.org/#x-user-defined)),
6
+ * and [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859) `iso-8859-*` mappings.
7
+ *
8
+ * ```js
9
+ * import { createSinglebyteDecoder, createSinglebyteEncoder } from '@exodus/bytes/single-byte.js'
10
+ * import { windows1252toString, windows1252fromString } from '@exodus/bytes/single-byte.js'
11
+ * import { latin1toString, latin1fromString } from '@exodus/bytes/single-byte.js'
12
+ * ```
13
+ *
14
+ * Supports all single-byte encodings listed in the WHATWG Encoding standard:
15
+ * `ibm866`, `iso-8859-2`, `iso-8859-3`, `iso-8859-4`, `iso-8859-5`, `iso-8859-6`, `iso-8859-7`, `iso-8859-8`,
16
+ * `iso-8859-8-i`, `iso-8859-10`, `iso-8859-13`, `iso-8859-14`, `iso-8859-15`, `iso-8859-16`, `koi8-r`, `koi8-u`,
17
+ * `macintosh`, `windows-874`, `windows-1250`, `windows-1251`, `windows-1252`, `windows-1253`, `windows-1254`,
18
+ * `windows-1255`, `windows-1256`, `windows-1257`, `windows-1258`, `x-mac-cyrillic` and `x-user-defined`.
19
+ *
20
+ * Also supports `iso-8859-1`, `iso-8859-9`, `iso-8859-11` as defined at
21
+ * [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859)
22
+ * (and all other `iso-8859-*` encodings there as they match WHATWG).
23
+ *
24
+ * > [!NOTE]
25
+ * > While all `iso-8859-*` encodings supported by the [WHATWG Encoding standard](https://encoding.spec.whatwg.org/) match
26
+ * > [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859), the WHATWG Encoding spec doesn't support
27
+ * > `iso-8859-1`, `iso-8859-9`, `iso-8859-11`, and instead maps them as labels to `windows-1252`, `windows-1254`, `windows-874`.\
28
+ * > `createSinglebyteDecoder()` (unlike `TextDecoder` or `legacyHookDecode()`) does not do such mapping,
29
+ * > so its results will differ from `TextDecoder` for those encoding names.
30
+ *
31
+ * ```js
32
+ * > new TextDecoder('iso-8859-1').encoding
33
+ * 'windows-1252'
34
+ * > new TextDecoder('iso-8859-9').encoding
35
+ * 'windows-1254'
36
+ * > new TextDecoder('iso-8859-11').encoding
37
+ * 'windows-874'
38
+ * > new TextDecoder('iso-8859-9').decode(Uint8Array.of(0x80, 0x81, 0xd0))
39
+ * '€\x81Ğ' // this is actually decoded according to windows-1254 per TextDecoder spec
40
+ * > createSinglebyteDecoder('iso-8859-9')(Uint8Array.of(0x80, 0x81, 0xd0))
41
+ * '\x80\x81Ğ' // this is iso-8859-9 as defined at https://unicode.org/Public/MAPPINGS/ISO8859/8859-9.txt
42
+ * ```
43
+ *
44
+ * All WHATWG Encoding spec [`windows-*` encodings](https://encoding.spec.whatwg.org/#windows-874) are supersets of
45
+ * corresponding [unicode.org encodings](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/), meaning that
46
+ * they encode/decode all the old valid (non-replacement) strings / byte sequences identically, but can also support
47
+ * a wider range of inputs.
48
+ *
49
+ * @module @exodus/bytes/single-byte.js
50
+ */
51
+
52
+ /// <reference types="node" />
53
+
54
+ import type { Uint8ArrayBuffer } from './array.js';
55
+
56
+ /**
57
+ * Create a decoder for a supported one-byte `encoding`, given its lowercased name `encoding`.
58
+ *
59
+ * Returns a function `decode(arr)` that decodes bytes to a string.
60
+ *
61
+ * @param encoding - The encoding name (e.g., 'iso-8859-1', 'windows-1252')
62
+ * @param loose - If true, replaces unmapped bytes with replacement character instead of throwing (default: false)
63
+ * @returns A function that decodes bytes to string
64
+ */
65
+ export function createSinglebyteDecoder(
66
+ encoding: string,
67
+ loose?: boolean
68
+ ): (arr: Uint8Array) => string;
69
+
70
+ /**
71
+ * Create an encoder for a supported one-byte `encoding`, given its lowercased name `encoding`.
72
+ *
73
+ * Returns a function `encode(string)` that encodes a string to bytes.
74
+ *
75
+ * In `'fatal'` mode (default), will throw on non well-formed strings or any codepoints which could
76
+ * not be encoded in the target encoding.
77
+ *
78
+ * @param encoding - The encoding name (e.g., 'iso-8859-1', 'windows-1252')
79
+ * @param options - Encoding options
80
+ * @param options.mode - Encoding mode (default: 'fatal'). Currently, only 'fatal' mode is supported.
81
+ * @returns A function that encodes string to bytes
82
+ */
83
+ export function createSinglebyteEncoder(
84
+ encoding: string,
85
+ options?: { mode?: 'fatal' }
86
+ ): (string: string) => Uint8ArrayBuffer;
87
+
88
+ /**
89
+ * Decode `iso-8859-1` bytes to a string.
90
+ *
91
+ * There is no loose variant for this encoding, all bytes can be decoded.
92
+ *
93
+ * Same as:
94
+ * ```js
95
+ * const latin1toString = createSinglebyteDecoder('iso-8859-1')
96
+ * ```
97
+ *
98
+ * Note: this is different from `new TextDecoder('iso-8859-1')` and `new TextDecoder('latin1')`, as
99
+ * those alias to `new TextDecoder('windows-1252')`.
100
+ *
101
+ * @param arr - The bytes to decode
102
+ * @returns The decoded string
103
+ */
104
+ export function latin1toString(arr: Uint8Array): string;
105
+
106
+ /**
107
+ * Encode a string to `iso-8859-1` bytes.
108
+ *
109
+ * Throws on non well-formed strings or any codepoints which could not be encoded in `iso-8859-1`.
110
+ *
111
+ * Same as:
112
+ * ```js
113
+ * const latin1fromString = createSinglebyteEncoder('iso-8859-1', { mode: 'fatal' })
114
+ * ```
115
+ *
116
+ * @param string - The string to encode
117
+ * @returns The encoded bytes
118
+ */
119
+ export function latin1fromString(string: string): Uint8ArrayBuffer;
120
+
121
+ /**
122
+ * Decode `windows-1252` bytes to a string.
123
+ *
124
+ * There is no loose variant for this encoding, all bytes can be decoded.
125
+ *
126
+ * Same as:
127
+ * ```js
128
+ * const windows1252toString = createSinglebyteDecoder('windows-1252')
129
+ * ```
130
+ *
131
+ * @param arr - The bytes to decode
132
+ * @returns The decoded string
133
+ */
134
+ export function windows1252toString(arr: Uint8Array): string;
135
+
136
+ /**
137
+ * Encode a string to `windows-1252` bytes.
138
+ *
139
+ * Throws on non well-formed strings or any codepoints which could not be encoded in `windows-1252`.
140
+ *
141
+ * Same as:
142
+ * ```js
143
+ * const windows1252fromString = createSinglebyteEncoder('windows-1252', { mode: 'fatal' })
144
+ * ```
145
+ *
146
+ * @param string - The string to encode
147
+ * @returns The encoded bytes
148
+ */
149
+ export function windows1252fromString(string: string): Uint8ArrayBuffer;
package/utf16.d.ts ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * UTF-16 encoding/decoding
3
+ *
4
+ * ```js
5
+ * import { utf16fromString, utf16toString } from '@exodus/bytes/utf16.js'
6
+ *
7
+ * // loose
8
+ * import { utf16fromStringLoose, utf16toStringLoose } from '@exodus/bytes/utf16.js'
9
+ * ```
10
+ *
11
+ * _These methods by design encode/decode BOM (codepoint `U+FEFF` Byte Order Mark) as-is._\
12
+ * _If you need BOM handling or detection, use `@exodus/bytes/encoding.js`_
13
+ *
14
+ * @module @exodus/bytes/utf16.js
15
+ */
16
+
17
+ /// <reference types="node" />
18
+
19
+ import type { Uint8ArrayBuffer, Uint16ArrayBuffer } from './array.js';
20
+
21
+ /**
22
+ * Output format for UTF-16 encoding
23
+ */
24
+ export type Utf16Format = 'uint16' | 'uint8-le' | 'uint8-be';
25
+
26
+ /**
27
+ * Encode a string to UTF-16 bytes (strict mode)
28
+ *
29
+ * Throws on invalid Unicode (unpaired surrogates)
30
+ *
31
+ * @param string - The string to encode
32
+ * @param format - Output format (default: 'uint16')
33
+ * @returns The encoded bytes
34
+ */
35
+ export function utf16fromString(string: string, format?: 'uint16'): Uint16ArrayBuffer;
36
+ export function utf16fromString(string: string, format: 'uint8-le'): Uint8ArrayBuffer;
37
+ export function utf16fromString(string: string, format: 'uint8-be'): Uint8ArrayBuffer;
38
+ export function utf16fromString(string: string, format?: Utf16Format): Uint16ArrayBuffer | Uint8ArrayBuffer;
39
+
40
+ /**
41
+ * Encode a string to UTF-16 bytes (loose mode)
42
+ *
43
+ * Replaces invalid Unicode (unpaired surrogates) with replacement codepoints `U+FFFD`
44
+ * per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
45
+ *
46
+ * _Such replacement is a non-injective function, is irreversible and causes collisions.\
47
+ * Prefer using strict throwing methods for cryptography applications._
48
+ *
49
+ * @param string - The string to encode
50
+ * @param format - Output format (default: 'uint16')
51
+ * @returns The encoded bytes
52
+ */
53
+ export function utf16fromStringLoose(string: string, format?: 'uint16'): Uint16ArrayBuffer;
54
+ export function utf16fromStringLoose(string: string, format: 'uint8-le'): Uint8ArrayBuffer;
55
+ export function utf16fromStringLoose(string: string, format: 'uint8-be'): Uint8ArrayBuffer;
56
+ export function utf16fromStringLoose(string: string, format?: Utf16Format): Uint16ArrayBuffer | Uint8ArrayBuffer;
57
+
58
+ /**
59
+ * Decode UTF-16 bytes to a string (strict mode)
60
+ *
61
+ * Throws on invalid UTF-16 byte sequences
62
+ *
63
+ * Throws on non-even byte length.
64
+ *
65
+ * @param arr - The bytes to decode
66
+ * @param format - Input format (default: 'uint16')
67
+ * @returns The decoded string
68
+ */
69
+ export function utf16toString(arr: Uint16Array, format?: 'uint16'): string;
70
+ export function utf16toString(arr: Uint8Array, format: 'uint8-le'): string;
71
+ export function utf16toString(arr: Uint8Array, format: 'uint8-be'): string;
72
+ export function utf16toString(arr: Uint16Array | Uint8Array, format?: Utf16Format): string;
73
+
74
+ /**
75
+ * Decode UTF-16 bytes to a string (loose mode)
76
+ *
77
+ * Replaces invalid UTF-16 byte sequences with replacement codepoints `U+FFFD`
78
+ * per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
79
+ *
80
+ * _Such replacement is a non-injective function, is irreversible and causes collisions.\
81
+ * Prefer using strict throwing methods for cryptography applications._
82
+ *
83
+ * Throws on non-even byte length.
84
+ *
85
+ * @param arr - The bytes to decode
86
+ * @param format - Input format (default: 'uint16')
87
+ * @returns The decoded string
88
+ */
89
+ export function utf16toStringLoose(arr: Uint16Array, format?: 'uint16'): string;
90
+ export function utf16toStringLoose(arr: Uint8Array, format: 'uint8-le'): string;
91
+ export function utf16toStringLoose(arr: Uint8Array, format: 'uint8-be'): string;
92
+ export function utf16toStringLoose(arr: Uint16Array | Uint8Array, format?: Utf16Format): string;
package/utf8.d.ts CHANGED
@@ -1,42 +1,76 @@
1
+ /**
2
+ * UTF-8 encoding/decoding
3
+ *
4
+ * ```js
5
+ * import { utf8fromString, utf8toString } from '@exodus/bytes/utf8.js'
6
+ *
7
+ * // loose
8
+ * import { utf8fromStringLoose, utf8toStringLoose } from '@exodus/bytes/utf8.js'
9
+ * ```
10
+ *
11
+ * _These methods by design encode/decode BOM (codepoint `U+FEFF` Byte Order Mark) as-is._\
12
+ * _If you need BOM handling or detection, use `@exodus/bytes/encoding.js`_
13
+ *
14
+ * @module @exodus/bytes/utf8.js
15
+ */
16
+
1
17
  /// <reference types="node" />
2
18
 
3
19
  import type { OutputFormat, Uint8ArrayBuffer } from './array.js';
4
20
 
5
21
  /**
6
- * Encodes a string to UTF-8 bytes (strict mode)
22
+ * Encode a string to UTF-8 bytes (strict mode)
23
+ *
7
24
  * Throws on invalid Unicode (unpaired surrogates)
8
- * @param str - The string to encode
25
+ *
26
+ * @param string - The string to encode
9
27
  * @param format - Output format (default: 'uint8')
10
28
  * @returns The encoded bytes
11
29
  */
12
- export function utf8fromString(str: string, format?: 'uint8'): Uint8ArrayBuffer;
13
- export function utf8fromString(str: string, format: 'buffer'): Buffer;
14
- export function utf8fromString(str: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer;
30
+ export function utf8fromString(string: string, format?: 'uint8'): Uint8ArrayBuffer;
31
+ export function utf8fromString(string: string, format: 'buffer'): Buffer;
32
+ export function utf8fromString(string: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer;
15
33
 
16
34
  /**
17
- * Encodes a string to UTF-8 bytes (loose mode)
18
- * Replaces invalid Unicode with replacement character
19
- * @param str - The string to encode
35
+ * Encode a string to UTF-8 bytes (loose mode)
36
+ *
37
+ * Replaces invalid Unicode (unpaired surrogates) with replacement codepoints `U+FFFD`
38
+ * per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
39
+ *
40
+ * _Such replacement is a non-injective function, is irreversable and causes collisions.\
41
+ * Prefer using strict throwing methods for cryptography applications._
42
+ *
43
+ * @param string - The string to encode
20
44
  * @param format - Output format (default: 'uint8')
21
45
  * @returns The encoded bytes
22
46
  */
23
- export function utf8fromStringLoose(str: string, format?: 'uint8'): Uint8ArrayBuffer;
24
- export function utf8fromStringLoose(str: string, format: 'buffer'): Buffer;
25
- export function utf8fromStringLoose(str: string, format?: OutputFormat): Uint8ArrayBuffer | Buffer;
47
+ export function utf8fromStringLoose(string: string, format?: 'uint8'): Uint8ArrayBuffer;
48
+ export function utf8fromStringLoose(string: string, format: 'buffer'): Buffer;
49
+ export function utf8fromStringLoose(
50
+ string: string,
51
+ format?: OutputFormat
52
+ ): Uint8ArrayBuffer | Buffer;
26
53
 
27
54
  /**
28
- * Decodes UTF-8 bytes to a string (strict mode)
29
- * Throws on invalid UTF-8 sequences
55
+ * Decode UTF-8 bytes to a string (strict mode)
56
+ *
57
+ * Throws on invalid UTF-8 byte sequences
58
+ *
30
59
  * @param arr - The bytes to decode
31
60
  * @returns The decoded string
32
61
  */
33
- export function utf8toString(arr: Uint8ArrayBuffer): string;
62
+ export function utf8toString(arr: Uint8Array): string;
34
63
 
35
64
  /**
36
- * Decodes UTF-8 bytes to a string (loose mode)
37
- * Replaces invalid sequences with replacement character
65
+ * Decode UTF-8 bytes to a string (loose mode)
66
+ *
67
+ * Replaces invalid UTF-8 byte sequences with replacement codepoints `U+FFFD`
68
+ * per [WHATWG Encoding](https://encoding.spec.whatwg.org/) specification.
69
+ *
70
+ * _Such replacement is a non-injective function, is irreversable and causes collisions.\
71
+ * Prefer using strict throwing methods for cryptography applications._
72
+ *
38
73
  * @param arr - The bytes to decode
39
74
  * @returns The decoded string
40
75
  */
41
- export function utf8toStringLoose(arr: Uint8ArrayBuffer): string;
42
-
76
+ export function utf8toStringLoose(arr: Uint8Array): string;
package/utf8.js CHANGED
@@ -35,8 +35,13 @@ function deLoose(str, loose, res) {
35
35
  start = pos + 1
36
36
  if (res[pos + 1] === 0xbf && res[pos + 2] === 0xbd) {
37
37
  // Found a replacement char in output, need to recheck if we encoded the input correctly
38
- if (str !== decode(res)) throw new TypeError(E_STRICT_UNICODE)
39
- return res
38
+ if (!nativeDecoder && str.length < 1e7) {
39
+ // This is ~2x faster than decode in Hermes
40
+ try {
41
+ if (encodeURI(str) !== null) return res // guard against optimizing out
42
+ } catch {}
43
+ } else if (str === decode(res)) return res
44
+ throw new TypeError(E_STRICT_UNICODE)
40
45
  }
41
46
  }
42
47
 
package/utf8.node.js CHANGED
@@ -9,7 +9,7 @@ if (Buffer.TYPED_ARRAY_SUPPORT) throw new Error('Unexpected Buffer polyfill')
9
9
  let decoderFatal
10
10
  const decoderLoose = new TextDecoder('utf-8', { ignoreBOM: true })
11
11
  const { isWellFormed } = String.prototype
12
- const isDeno = Boolean(globalThis.Deno)
12
+ const isDeno = !!globalThis.Deno
13
13
 
14
14
  try {
15
15
  decoderFatal = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true })
package/wif.d.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Wallet Import Format (WIF) encoding and decoding.
3
+ *
4
+ * ```js
5
+ * import { fromWifString, toWifString } from '@exodus/bytes/wif.js'
6
+ * import { fromWifStringSync, toWifStringSync } from '@exodus/bytes/wif.js'
7
+ * ```
8
+ *
9
+ * On non-Node.js, requires peer dependency [@noble/hashes](https://www.npmjs.com/package/@noble/hashes) to be installed.
10
+ *
11
+ * @module @exodus/bytes/wif.js
12
+ */
13
+
14
+ /// <reference types="node" />
15
+
16
+ import type { Uint8ArrayBuffer } from './array.js';
17
+
18
+ /**
19
+ * WIF (Wallet Import Format) data structure
20
+ */
21
+ export interface Wif {
22
+ /** Network version byte */
23
+ version: number;
24
+ /** 32-byte private key */
25
+ privateKey: Uint8ArrayBuffer;
26
+ /** Whether the key is compressed */
27
+ compressed: boolean;
28
+ }
29
+
30
+ /**
31
+ * Decode a WIF string to WIF data
32
+ *
33
+ * Returns a promise that resolves to an object with `{ version, privateKey, compressed }`.
34
+ *
35
+ * The optional `version` parameter validates the version byte.
36
+ *
37
+ * Throws if the WIF string is invalid or version doesn't match.
38
+ *
39
+ * @param string - The WIF encoded string
40
+ * @param version - Optional expected version byte to validate against
41
+ * @returns The decoded WIF data
42
+ * @throws Error if the WIF string is invalid or version doesn't match
43
+ */
44
+ export function fromWifString(string: string, version?: number): Promise<Wif>;
45
+
46
+ /**
47
+ * Decode a WIF string to WIF data (synchronous)
48
+ *
49
+ * Returns an object with `{ version, privateKey, compressed }`.
50
+ *
51
+ * The optional `version` parameter validates the version byte.
52
+ *
53
+ * Throws if the WIF string is invalid or version doesn't match.
54
+ *
55
+ * @param string - The WIF encoded string
56
+ * @param version - Optional expected version byte to validate against
57
+ * @returns The decoded WIF data
58
+ * @throws Error if the WIF string is invalid or version doesn't match
59
+ */
60
+ export function fromWifStringSync(string: string, version?: number): Wif;
61
+
62
+ /**
63
+ * Encode WIF data to a WIF string
64
+ *
65
+ * @param wif - The WIF data to encode
66
+ * @returns The WIF encoded string
67
+ */
68
+ export function toWifString(wif: Wif): Promise<string>;
69
+
70
+ /**
71
+ * Encode WIF data to a WIF string (synchronous)
72
+ *
73
+ * @param wif - The WIF data to encode
74
+ * @returns The WIF encoded string
75
+ */
76
+ export function toWifStringSync(wif: Wif): string;