@metamask/utils 3.0.3 → 3.2.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/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.2.0]
10
+ ### Added
11
+ - Add `PendingJsonRpcResponse` type ([#43](https://github.com/MetaMask/utils/pull/43))
12
+ - Add utils for converting between numbers and hex ([#41](https://github.com/MetaMask/utils/pull/41))
13
+ - Add coercion utils ([#38](https://github.com/MetaMask/utils/pull/38))
14
+
15
+ ## [3.1.0]
16
+ ### Added
17
+ - Add assertion utils ([#33](https://github.com/MetaMask/utils/pull/33))
18
+ - Add util functions for encoding and decoding bytes ([#34](https://github.com/MetaMask/utils/pull/34))
19
+
20
+ ### Fixed
21
+ - Make JSON-RPC error `data` property optional ([#31](https://github.com/MetaMask/utils/pull/31))
22
+ - Don't include test files in dist folder ([#35](https://github.com/MetaMask/utils/pull/35))
23
+ - Fix typo in README ([#28](https://github.com/MetaMask/utils/pull/28))
24
+
9
25
  ## [3.0.3]
10
26
  ### Fixed
11
27
  - Allow omitting JSON-RPC params when params can be undefined ([#29](https://github.com/MetaMask/utils/pull/29))
@@ -63,7 +79,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
63
79
  ### Added
64
80
  - Initial release
65
81
 
66
- [Unreleased]: https://github.com/MetaMask/utils/compare/v3.0.3...HEAD
82
+ [Unreleased]: https://github.com/MetaMask/utils/compare/v3.2.0...HEAD
83
+ [3.2.0]: https://github.com/MetaMask/utils/compare/v3.1.0...v3.2.0
84
+ [3.1.0]: https://github.com/MetaMask/utils/compare/v3.0.3...v3.1.0
67
85
  [3.0.3]: https://github.com/MetaMask/utils/compare/v3.0.2...v3.0.3
68
86
  [3.0.2]: https://github.com/MetaMask/utils/compare/v3.0.1...v3.0.2
69
87
  [3.0.1]: https://github.com/MetaMask/utils/compare/v3.0.0...v3.0.1
package/README.md CHANGED
@@ -21,7 +21,7 @@ The full API documentation for the latest published version of this library is [
21
21
  - Install [Node.js](https://nodejs.org) version 12
22
22
  - If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you.
23
23
  - Install [Yarn v1](https://yarnpkg.com/en/docs/install)
24
- - Run `yarn setup` to install dependencies and run any requried post-install scripts
24
+ - Run `yarn setup` to install dependencies and run any required post-install scripts
25
25
  - **Warning:** Do not use the `yarn` / `yarn install` command directly. Use `yarn setup` instead. The normal install command will skip required post-install scripts, leaving your development environment in an invalid state.
26
26
 
27
27
  ### Testing and Linting
@@ -0,0 +1,36 @@
1
+ export declare class AssertionError extends Error {
2
+ readonly code = "ERR_ASSERTION";
3
+ constructor(options: {
4
+ message: string;
5
+ });
6
+ }
7
+ /**
8
+ * Same as Node.js assert.
9
+ * If the value is falsy, throws an error, does nothing otherwise.
10
+ *
11
+ * @throws {@link AssertionError}. If value is falsy.
12
+ * @param value - The test that should be truthy to pass.
13
+ * @param message - Message to be passed to {@link AssertionError} or an
14
+ * {@link Error} instance to throw.
15
+ */
16
+ export declare function assert(value: any, message?: string | Error): asserts value;
17
+ /**
18
+ * Use in the default case of a switch that you want to be fully exhaustive.
19
+ * Using this function forces the compiler to enforce exhaustivity during
20
+ * compile-time.
21
+ *
22
+ * @example
23
+ * ```
24
+ * const number = 1;
25
+ * switch (number) {
26
+ * case 0:
27
+ * ...
28
+ * case 1:
29
+ * ...
30
+ * default:
31
+ * assertExhaustive(snapPrefix);
32
+ * }
33
+ * ```
34
+ * @param _object - The object on which the switch is being operated.
35
+ */
36
+ export declare function assertExhaustive(_object: never): never;
package/dist/assert.js ADDED
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertExhaustive = exports.assert = exports.AssertionError = void 0;
4
+ class AssertionError extends Error {
5
+ constructor(options) {
6
+ super(options.message);
7
+ this.code = 'ERR_ASSERTION';
8
+ }
9
+ }
10
+ exports.AssertionError = AssertionError;
11
+ /**
12
+ * Same as Node.js assert.
13
+ * If the value is falsy, throws an error, does nothing otherwise.
14
+ *
15
+ * @throws {@link AssertionError}. If value is falsy.
16
+ * @param value - The test that should be truthy to pass.
17
+ * @param message - Message to be passed to {@link AssertionError} or an
18
+ * {@link Error} instance to throw.
19
+ */
20
+ function assert(value, message) {
21
+ if (!value) {
22
+ if (message instanceof Error) {
23
+ throw message;
24
+ }
25
+ throw new AssertionError({ message: message !== null && message !== void 0 ? message : 'Assertion failed.' });
26
+ }
27
+ }
28
+ exports.assert = assert;
29
+ /**
30
+ * Use in the default case of a switch that you want to be fully exhaustive.
31
+ * Using this function forces the compiler to enforce exhaustivity during
32
+ * compile-time.
33
+ *
34
+ * @example
35
+ * ```
36
+ * const number = 1;
37
+ * switch (number) {
38
+ * case 0:
39
+ * ...
40
+ * case 1:
41
+ * ...
42
+ * default:
43
+ * assertExhaustive(snapPrefix);
44
+ * }
45
+ * ```
46
+ * @param _object - The object on which the switch is being operated.
47
+ */
48
+ function assertExhaustive(_object) {
49
+ throw new Error('Invalid branch reached. Should be detected during compilation.');
50
+ }
51
+ exports.assertExhaustive = assertExhaustive;
52
+ //# sourceMappingURL=assert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert.js","sourceRoot":"","sources":["../src/assert.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAe,SAAQ,KAAK;IAGvC,YAAY,OAA4B;QACtC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAHhB,SAAI,GAAG,eAAe,CAAC;IAIhC,CAAC;CACF;AAND,wCAMC;AAED;;;;;;;;GAQG;AACH,SAAgB,MAAM,CAAC,KAAU,EAAE,OAAwB;IACzD,IAAI,CAAC,KAAK,EAAE;QACV,IAAI,OAAO,YAAY,KAAK,EAAE;YAC5B,MAAM,OAAO,CAAC;SACf;QACD,MAAM,IAAI,cAAc,CAAC,EAAE,OAAO,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,mBAAmB,EAAE,CAAC,CAAC;KACvE;AACH,CAAC;AAPD,wBAOC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,gBAAgB,CAAC,OAAc;IAC7C,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;AACJ,CAAC;AAJD,4CAIC","sourcesContent":["export class AssertionError extends Error {\n readonly code = 'ERR_ASSERTION';\n\n constructor(options: { message: string }) {\n super(options.message);\n }\n}\n\n/**\n * Same as Node.js assert.\n * If the value is falsy, throws an error, does nothing otherwise.\n *\n * @throws {@link AssertionError}. If value is falsy.\n * @param value - The test that should be truthy to pass.\n * @param message - Message to be passed to {@link AssertionError} or an\n * {@link Error} instance to throw.\n */\nexport function assert(value: any, message?: string | Error): asserts value {\n if (!value) {\n if (message instanceof Error) {\n throw message;\n }\n throw new AssertionError({ message: message ?? 'Assertion failed.' });\n }\n}\n\n/**\n * Use in the default case of a switch that you want to be fully exhaustive.\n * Using this function forces the compiler to enforce exhaustivity during\n * compile-time.\n *\n * @example\n * ```\n * const number = 1;\n * switch (number) {\n * case 0:\n * ...\n * case 1:\n * ...\n * default:\n * assertExhaustive(snapPrefix);\n * }\n * ```\n * @param _object - The object on which the switch is being operated.\n */\nexport function assertExhaustive(_object: never): never {\n throw new Error(\n 'Invalid branch reached. Should be detected during compilation.',\n );\n}\n"]}
@@ -0,0 +1,145 @@
1
+ import { Hex } from './hex';
2
+ export declare type Bytes = bigint | number | string | Uint8Array;
3
+ /**
4
+ * Check if a value is a `Uint8Array`.
5
+ *
6
+ * @param value - The value to check.
7
+ * @returns Whether the value is a `Uint8Array`.
8
+ */
9
+ export declare function isBytes(value: unknown): value is Uint8Array;
10
+ /**
11
+ * Assert that a value is a `Uint8Array`.
12
+ *
13
+ * @param value - The value to check.
14
+ * @throws If the value is not a `Uint8Array`.
15
+ */
16
+ export declare function assertIsBytes(value: unknown): asserts value is Uint8Array;
17
+ /**
18
+ * Convert a `Uint8Array` to a hexadecimal string.
19
+ *
20
+ * @param bytes - The bytes to convert to a hexadecimal string.
21
+ * @returns The hexadecimal string.
22
+ */
23
+ export declare function bytesToHex(bytes: Uint8Array): Hex;
24
+ /**
25
+ * Convert a `Uint8Array` to a `bigint`.
26
+ *
27
+ * To convert a `Uint8Array` to a `number` instead, use {@link bytesToNumber}.
28
+ * To convert a two's complement encoded `Uint8Array` to a `bigint`, use
29
+ * {@link bytesToSignedBigInt}.
30
+ *
31
+ * @param bytes - The bytes to convert to a `bigint`.
32
+ * @returns The `bigint`.
33
+ */
34
+ export declare function bytesToBigInt(bytes: Uint8Array): bigint;
35
+ /**
36
+ * Convert a `Uint8Array` to a signed `bigint`. This assumes that the bytes are
37
+ * encoded in two's complement.
38
+ *
39
+ * To convert a `Uint8Array` to an unsigned `bigint` instead, use
40
+ * {@link bytesToBigInt}.
41
+ *
42
+ * @see https://en.wikipedia.org/wiki/Two%27s_complement
43
+ * @param bytes - The bytes to convert to a signed `bigint`.
44
+ * @returns The signed `bigint`.
45
+ */
46
+ export declare function bytesToSignedBigInt(bytes: Uint8Array): bigint;
47
+ /**
48
+ * Convert a `Uint8Array` to a `number`.
49
+ *
50
+ * To convert a `Uint8Array` to a `bigint` instead, use {@link bytesToBigInt}.
51
+ *
52
+ * @param bytes - The bytes to convert to a number.
53
+ * @returns The number.
54
+ * @throws If the resulting number is not a safe integer.
55
+ */
56
+ export declare function bytesToNumber(bytes: Uint8Array): number;
57
+ /**
58
+ * Convert a UTF-8 encoded `Uint8Array` to a `string`.
59
+ *
60
+ * @param bytes - The bytes to convert to a string.
61
+ * @returns The string.
62
+ */
63
+ export declare function bytesToString(bytes: Uint8Array): string;
64
+ /**
65
+ * Convert a hexadecimal string to a `Uint8Array`. The string can optionally be
66
+ * prefixed with `0x`. It accepts even and odd length strings.
67
+ *
68
+ * If the value is "0x", an empty `Uint8Array` is returned.
69
+ *
70
+ * @param value - The hexadecimal string to convert to bytes.
71
+ * @returns The bytes as `Uint8Array`.
72
+ */
73
+ export declare function hexToBytes(value: string): Uint8Array;
74
+ /**
75
+ * Convert a `bigint` to a `Uint8Array`.
76
+ *
77
+ * This assumes that the `bigint` is an unsigned integer. To convert a signed
78
+ * `bigint` instead, use {@link signedBigIntToBytes}.
79
+ *
80
+ * @param value - The bigint to convert to bytes.
81
+ * @returns The bytes as `Uint8Array`.
82
+ */
83
+ export declare function bigIntToBytes(value: bigint): Uint8Array;
84
+ /**
85
+ * Convert a signed `bigint` to a `Uint8Array`. This uses two's complement
86
+ * encoding to represent negative numbers.
87
+ *
88
+ * To convert an unsigned `bigint` to a `Uint8Array` instead, use
89
+ * {@link bigIntToBytes}.
90
+ *
91
+ * @see https://en.wikipedia.org/wiki/Two%27s_complement
92
+ * @param value - The number to convert to bytes.
93
+ * @param byteLength - The length of the resulting `Uint8Array`. If the number
94
+ * is larger than the maximum value that can be represented by the given length,
95
+ * an error is thrown.
96
+ * @returns The bytes as `Uint8Array`.
97
+ */
98
+ export declare function signedBigIntToBytes(value: bigint, byteLength: number): Uint8Array;
99
+ /**
100
+ * Convert a `number` to a `Uint8Array`.
101
+ *
102
+ * @param value - The number to convert to bytes.
103
+ * @returns The bytes as `Uint8Array`.
104
+ * @throws If the number is not a safe integer.
105
+ */
106
+ export declare function numberToBytes(value: number): Uint8Array;
107
+ /**
108
+ * Convert a `string` to a UTF-8 encoded `Uint8Array`.
109
+ *
110
+ * @param value - The string to convert to bytes.
111
+ * @returns The bytes as `Uint8Array`.
112
+ */
113
+ export declare function stringToBytes(value: string): Uint8Array;
114
+ /**
115
+ * Convert a byte-like value to a `Uint8Array`. The value can be a `Uint8Array`,
116
+ * a `bigint`, a `number`, or a `string`.
117
+ *
118
+ * This will attempt to guess the type of the value based on its type and
119
+ * contents. For more control over the conversion, use the more specific
120
+ * conversion functions, such as {@link hexToBytes} or {@link stringToBytes}.
121
+ *
122
+ * If the value is a `string`, and it is prefixed with `0x`, it will be
123
+ * interpreted as a hexadecimal string. Otherwise, it will be interpreted as a
124
+ * UTF-8 string. To convert a hexadecimal string to bytes without interpreting
125
+ * it as a UTF-8 string, use {@link hexToBytes} instead.
126
+ *
127
+ * If the value is a `bigint`, it is assumed to be unsigned. To convert a signed
128
+ * `bigint` to bytes, use {@link signedBigIntToBytes} instead.
129
+ *
130
+ * If the value is a `Uint8Array`, it will be returned as-is.
131
+ *
132
+ * @param value - The value to convert to bytes.
133
+ * @returns The bytes as `Uint8Array`.
134
+ */
135
+ export declare function valueToBytes(value: Bytes): Uint8Array;
136
+ /**
137
+ * Concatenate multiple byte-like values into a single `Uint8Array`. The values
138
+ * can be `Uint8Array`, `bigint`, `number`, or `string`. This uses
139
+ * {@link valueToBytes} under the hood to convert each value to bytes. Refer to
140
+ * the documentation of that function for more information.
141
+ *
142
+ * @param values - The values to concatenate.
143
+ * @returns The concatenated bytes as `Uint8Array`.
144
+ */
145
+ export declare function concatBytes(values: Bytes[]): Uint8Array;
package/dist/bytes.js ADDED
@@ -0,0 +1,344 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.concatBytes = exports.valueToBytes = exports.stringToBytes = exports.numberToBytes = exports.signedBigIntToBytes = exports.bigIntToBytes = exports.hexToBytes = exports.bytesToString = exports.bytesToNumber = exports.bytesToSignedBigInt = exports.bytesToBigInt = exports.bytesToHex = exports.assertIsBytes = exports.isBytes = void 0;
4
+ const assert_1 = require("./assert");
5
+ const hex_1 = require("./hex");
6
+ // '0'.charCodeAt(0) === 48
7
+ const HEX_MINIMUM_NUMBER_CHARACTER = 48;
8
+ // '9'.charCodeAt(0) === 57
9
+ const HEX_MAXIMUM_NUMBER_CHARACTER = 58;
10
+ const HEX_CHARACTER_OFFSET = 87;
11
+ /**
12
+ * Memoized function that returns an array to be used as a lookup table for
13
+ * converting bytes to hexadecimal values.
14
+ *
15
+ * The array is created lazily and then cached for future use. The benefit of
16
+ * this approach is that the performance of converting bytes to hex is much
17
+ * better than if we were to call `toString(16)` on each byte.
18
+ *
19
+ * The downside is that the array is created once and then never garbage
20
+ * collected. This is not a problem in practice because the array is only 256
21
+ * elements long.
22
+ *
23
+ * @returns A function that returns the lookup table.
24
+ */
25
+ function getPrecomputedHexValuesBuilder() {
26
+ // To avoid issues with tree shaking, we need to use a function to return the
27
+ // array. This is because the array is only used in the `bytesToHex` function
28
+ // and if we were to use a global variable, the array might be removed by the
29
+ // tree shaker.
30
+ const lookupTable = [];
31
+ return () => {
32
+ if (lookupTable.length === 0) {
33
+ for (let i = 0; i < 256; i++) {
34
+ lookupTable.push(i.toString(16).padStart(2, '0'));
35
+ }
36
+ }
37
+ return lookupTable;
38
+ };
39
+ }
40
+ /**
41
+ * Function implementation of the {@link getPrecomputedHexValuesBuilder}
42
+ * function.
43
+ */
44
+ const getPrecomputedHexValues = getPrecomputedHexValuesBuilder();
45
+ /**
46
+ * Check if a value is a `Uint8Array`.
47
+ *
48
+ * @param value - The value to check.
49
+ * @returns Whether the value is a `Uint8Array`.
50
+ */
51
+ function isBytes(value) {
52
+ return value instanceof Uint8Array;
53
+ }
54
+ exports.isBytes = isBytes;
55
+ /**
56
+ * Assert that a value is a `Uint8Array`.
57
+ *
58
+ * @param value - The value to check.
59
+ * @throws If the value is not a `Uint8Array`.
60
+ */
61
+ function assertIsBytes(value) {
62
+ (0, assert_1.assert)(isBytes(value), 'Value must be a Uint8Array.');
63
+ }
64
+ exports.assertIsBytes = assertIsBytes;
65
+ /**
66
+ * Convert a `Uint8Array` to a hexadecimal string.
67
+ *
68
+ * @param bytes - The bytes to convert to a hexadecimal string.
69
+ * @returns The hexadecimal string.
70
+ */
71
+ function bytesToHex(bytes) {
72
+ assertIsBytes(bytes);
73
+ if (bytes.length === 0) {
74
+ return '0x';
75
+ }
76
+ const lookupTable = getPrecomputedHexValues();
77
+ const hex = new Array(bytes.length);
78
+ for (let i = 0; i < bytes.length; i++) {
79
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
80
+ hex[i] = lookupTable[bytes[i]];
81
+ }
82
+ return (0, hex_1.add0x)(hex.join(''));
83
+ }
84
+ exports.bytesToHex = bytesToHex;
85
+ /**
86
+ * Convert a `Uint8Array` to a `bigint`.
87
+ *
88
+ * To convert a `Uint8Array` to a `number` instead, use {@link bytesToNumber}.
89
+ * To convert a two's complement encoded `Uint8Array` to a `bigint`, use
90
+ * {@link bytesToSignedBigInt}.
91
+ *
92
+ * @param bytes - The bytes to convert to a `bigint`.
93
+ * @returns The `bigint`.
94
+ */
95
+ function bytesToBigInt(bytes) {
96
+ assertIsBytes(bytes);
97
+ const hex = bytesToHex(bytes);
98
+ return BigInt(hex);
99
+ }
100
+ exports.bytesToBigInt = bytesToBigInt;
101
+ /**
102
+ * Convert a `Uint8Array` to a signed `bigint`. This assumes that the bytes are
103
+ * encoded in two's complement.
104
+ *
105
+ * To convert a `Uint8Array` to an unsigned `bigint` instead, use
106
+ * {@link bytesToBigInt}.
107
+ *
108
+ * @see https://en.wikipedia.org/wiki/Two%27s_complement
109
+ * @param bytes - The bytes to convert to a signed `bigint`.
110
+ * @returns The signed `bigint`.
111
+ */
112
+ function bytesToSignedBigInt(bytes) {
113
+ assertIsBytes(bytes);
114
+ let value = BigInt(0);
115
+ for (const byte of bytes) {
116
+ // eslint-disable-next-line no-bitwise
117
+ value = (value << BigInt(8)) + BigInt(byte);
118
+ }
119
+ return BigInt.asIntN(bytes.length * 8, value);
120
+ }
121
+ exports.bytesToSignedBigInt = bytesToSignedBigInt;
122
+ /**
123
+ * Convert a `Uint8Array` to a `number`.
124
+ *
125
+ * To convert a `Uint8Array` to a `bigint` instead, use {@link bytesToBigInt}.
126
+ *
127
+ * @param bytes - The bytes to convert to a number.
128
+ * @returns The number.
129
+ * @throws If the resulting number is not a safe integer.
130
+ */
131
+ function bytesToNumber(bytes) {
132
+ assertIsBytes(bytes);
133
+ const bigint = bytesToBigInt(bytes);
134
+ (0, assert_1.assert)(bigint <= BigInt(Number.MAX_SAFE_INTEGER), 'Number is not a safe integer. Use `bytesToBigInt` instead.');
135
+ return Number(bigint);
136
+ }
137
+ exports.bytesToNumber = bytesToNumber;
138
+ /**
139
+ * Convert a UTF-8 encoded `Uint8Array` to a `string`.
140
+ *
141
+ * @param bytes - The bytes to convert to a string.
142
+ * @returns The string.
143
+ */
144
+ function bytesToString(bytes) {
145
+ assertIsBytes(bytes);
146
+ return new TextDecoder().decode(bytes);
147
+ }
148
+ exports.bytesToString = bytesToString;
149
+ /**
150
+ * Convert a hexadecimal string to a `Uint8Array`. The string can optionally be
151
+ * prefixed with `0x`. It accepts even and odd length strings.
152
+ *
153
+ * If the value is "0x", an empty `Uint8Array` is returned.
154
+ *
155
+ * @param value - The hexadecimal string to convert to bytes.
156
+ * @returns The bytes as `Uint8Array`.
157
+ */
158
+ function hexToBytes(value) {
159
+ var _a;
160
+ // "0x" is often used as empty byte array.
161
+ if (((_a = value === null || value === void 0 ? void 0 : value.toLowerCase) === null || _a === void 0 ? void 0 : _a.call(value)) === '0x') {
162
+ return new Uint8Array();
163
+ }
164
+ (0, hex_1.assertIsHexString)(value);
165
+ // Remove the `0x` prefix if it exists, and pad the string to have an even
166
+ // number of characters.
167
+ const strippedValue = (0, hex_1.remove0x)(value).toLowerCase();
168
+ const normalizedValue = strippedValue.length % 2 === 0 ? strippedValue : `0${strippedValue}`;
169
+ const bytes = new Uint8Array(normalizedValue.length / 2);
170
+ for (let i = 0; i < bytes.length; i++) {
171
+ // While this is not the prettiest way to convert a hexadecimal string to a
172
+ // `Uint8Array`, it is a lot faster than using `parseInt` to convert each
173
+ // character.
174
+ const c1 = normalizedValue.charCodeAt(i * 2);
175
+ const c2 = normalizedValue.charCodeAt(i * 2 + 1);
176
+ const n1 = c1 -
177
+ (c1 < HEX_MAXIMUM_NUMBER_CHARACTER
178
+ ? HEX_MINIMUM_NUMBER_CHARACTER
179
+ : HEX_CHARACTER_OFFSET);
180
+ const n2 = c2 -
181
+ (c2 < HEX_MAXIMUM_NUMBER_CHARACTER
182
+ ? HEX_MINIMUM_NUMBER_CHARACTER
183
+ : HEX_CHARACTER_OFFSET);
184
+ bytes[i] = n1 * 16 + n2;
185
+ }
186
+ return bytes;
187
+ }
188
+ exports.hexToBytes = hexToBytes;
189
+ /**
190
+ * Convert a `bigint` to a `Uint8Array`.
191
+ *
192
+ * This assumes that the `bigint` is an unsigned integer. To convert a signed
193
+ * `bigint` instead, use {@link signedBigIntToBytes}.
194
+ *
195
+ * @param value - The bigint to convert to bytes.
196
+ * @returns The bytes as `Uint8Array`.
197
+ */
198
+ function bigIntToBytes(value) {
199
+ (0, assert_1.assert)(typeof value === 'bigint', 'Value must be a bigint.');
200
+ (0, assert_1.assert)(value >= BigInt(0), 'Value must be a non-negative bigint.');
201
+ const hex = value.toString(16);
202
+ return hexToBytes(hex);
203
+ }
204
+ exports.bigIntToBytes = bigIntToBytes;
205
+ /**
206
+ * Check if a `bigint` fits in a certain number of bytes.
207
+ *
208
+ * @param value - The `bigint` to check.
209
+ * @param bytes - The number of bytes.
210
+ * @returns Whether the `bigint` fits in the number of bytes.
211
+ */
212
+ function bigIntFits(value, bytes) {
213
+ (0, assert_1.assert)(bytes > 0);
214
+ /* eslint-disable no-bitwise */
215
+ const mask = value >> BigInt(31);
216
+ return !(((~value & mask) + (value & ~mask)) >> BigInt(bytes * 8 + ~0));
217
+ /* eslint-enable no-bitwise */
218
+ }
219
+ /**
220
+ * Convert a signed `bigint` to a `Uint8Array`. This uses two's complement
221
+ * encoding to represent negative numbers.
222
+ *
223
+ * To convert an unsigned `bigint` to a `Uint8Array` instead, use
224
+ * {@link bigIntToBytes}.
225
+ *
226
+ * @see https://en.wikipedia.org/wiki/Two%27s_complement
227
+ * @param value - The number to convert to bytes.
228
+ * @param byteLength - The length of the resulting `Uint8Array`. If the number
229
+ * is larger than the maximum value that can be represented by the given length,
230
+ * an error is thrown.
231
+ * @returns The bytes as `Uint8Array`.
232
+ */
233
+ function signedBigIntToBytes(value, byteLength) {
234
+ (0, assert_1.assert)(typeof value === 'bigint', 'Value must be a bigint.');
235
+ (0, assert_1.assert)(typeof byteLength === 'number', 'Byte length must be a number.');
236
+ (0, assert_1.assert)(byteLength > 0, 'Byte length must be greater than 0.');
237
+ (0, assert_1.assert)(bigIntFits(value, byteLength), 'Byte length is too small to represent the given value.');
238
+ // ESLint doesn't like mutating function parameters, so to avoid having to
239
+ // disable the rule, we create a new variable.
240
+ let numberValue = value;
241
+ const bytes = new Uint8Array(byteLength);
242
+ for (let i = 0; i < bytes.length; i++) {
243
+ bytes[i] = Number(BigInt.asUintN(8, numberValue));
244
+ // eslint-disable-next-line no-bitwise
245
+ numberValue >>= BigInt(8);
246
+ }
247
+ return bytes.reverse();
248
+ }
249
+ exports.signedBigIntToBytes = signedBigIntToBytes;
250
+ /**
251
+ * Convert a `number` to a `Uint8Array`.
252
+ *
253
+ * @param value - The number to convert to bytes.
254
+ * @returns The bytes as `Uint8Array`.
255
+ * @throws If the number is not a safe integer.
256
+ */
257
+ function numberToBytes(value) {
258
+ (0, assert_1.assert)(typeof value === 'number', 'Value must be a number.');
259
+ (0, assert_1.assert)(value >= 0, 'Value must be a non-negative number.');
260
+ (0, assert_1.assert)(Number.isSafeInteger(value), 'Value is not a safe integer. Use `bigIntToBytes` instead.');
261
+ const hex = value.toString(16);
262
+ return hexToBytes(hex);
263
+ }
264
+ exports.numberToBytes = numberToBytes;
265
+ /**
266
+ * Convert a `string` to a UTF-8 encoded `Uint8Array`.
267
+ *
268
+ * @param value - The string to convert to bytes.
269
+ * @returns The bytes as `Uint8Array`.
270
+ */
271
+ function stringToBytes(value) {
272
+ (0, assert_1.assert)(typeof value === 'string', 'Value must be a string.');
273
+ return new TextEncoder().encode(value);
274
+ }
275
+ exports.stringToBytes = stringToBytes;
276
+ /**
277
+ * Convert a byte-like value to a `Uint8Array`. The value can be a `Uint8Array`,
278
+ * a `bigint`, a `number`, or a `string`.
279
+ *
280
+ * This will attempt to guess the type of the value based on its type and
281
+ * contents. For more control over the conversion, use the more specific
282
+ * conversion functions, such as {@link hexToBytes} or {@link stringToBytes}.
283
+ *
284
+ * If the value is a `string`, and it is prefixed with `0x`, it will be
285
+ * interpreted as a hexadecimal string. Otherwise, it will be interpreted as a
286
+ * UTF-8 string. To convert a hexadecimal string to bytes without interpreting
287
+ * it as a UTF-8 string, use {@link hexToBytes} instead.
288
+ *
289
+ * If the value is a `bigint`, it is assumed to be unsigned. To convert a signed
290
+ * `bigint` to bytes, use {@link signedBigIntToBytes} instead.
291
+ *
292
+ * If the value is a `Uint8Array`, it will be returned as-is.
293
+ *
294
+ * @param value - The value to convert to bytes.
295
+ * @returns The bytes as `Uint8Array`.
296
+ */
297
+ function valueToBytes(value) {
298
+ if (typeof value === 'bigint') {
299
+ return bigIntToBytes(value);
300
+ }
301
+ if (typeof value === 'number') {
302
+ return numberToBytes(value);
303
+ }
304
+ if (typeof value === 'string') {
305
+ if (value.startsWith('0x')) {
306
+ return hexToBytes(value);
307
+ }
308
+ return stringToBytes(value);
309
+ }
310
+ if (isBytes(value)) {
311
+ return value;
312
+ }
313
+ throw new TypeError(`Unsupported value type: "${typeof value}".`);
314
+ }
315
+ exports.valueToBytes = valueToBytes;
316
+ /**
317
+ * Concatenate multiple byte-like values into a single `Uint8Array`. The values
318
+ * can be `Uint8Array`, `bigint`, `number`, or `string`. This uses
319
+ * {@link valueToBytes} under the hood to convert each value to bytes. Refer to
320
+ * the documentation of that function for more information.
321
+ *
322
+ * @param values - The values to concatenate.
323
+ * @returns The concatenated bytes as `Uint8Array`.
324
+ */
325
+ function concatBytes(values) {
326
+ const normalizedValues = new Array(values.length);
327
+ let byteLength = 0;
328
+ for (let i = 0; i < values.length; i++) {
329
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
330
+ const value = valueToBytes(values[i]);
331
+ normalizedValues[i] = value;
332
+ byteLength += value.length;
333
+ }
334
+ const bytes = new Uint8Array(byteLength);
335
+ for (let i = 0, offset = 0; i < normalizedValues.length; i++) {
336
+ // While we could simply spread the values into an array and use
337
+ // `Uint8Array.from`, that is a lot slower than using `Uint8Array.set`.
338
+ bytes.set(normalizedValues[i], offset);
339
+ offset += normalizedValues[i].length;
340
+ }
341
+ return bytes;
342
+ }
343
+ exports.concatBytes = concatBytes;
344
+ //# sourceMappingURL=bytes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from './assert';\nimport { add0x, assertIsHexString, Hex, remove0x } from './hex';\n\n// '0'.charCodeAt(0) === 48\nconst HEX_MINIMUM_NUMBER_CHARACTER = 48;\n\n// '9'.charCodeAt(0) === 57\nconst HEX_MAXIMUM_NUMBER_CHARACTER = 58;\nconst HEX_CHARACTER_OFFSET = 87;\n\nexport type Bytes = bigint | number | string | Uint8Array;\n\n/**\n * Memoized function that returns an array to be used as a lookup table for\n * converting bytes to hexadecimal values.\n *\n * The array is created lazily and then cached for future use. The benefit of\n * this approach is that the performance of converting bytes to hex is much\n * better than if we were to call `toString(16)` on each byte.\n *\n * The downside is that the array is created once and then never garbage\n * collected. This is not a problem in practice because the array is only 256\n * elements long.\n *\n * @returns A function that returns the lookup table.\n */\nfunction getPrecomputedHexValuesBuilder(): () => string[] {\n // To avoid issues with tree shaking, we need to use a function to return the\n // array. This is because the array is only used in the `bytesToHex` function\n // and if we were to use a global variable, the array might be removed by the\n // tree shaker.\n const lookupTable: string[] = [];\n\n return () => {\n if (lookupTable.length === 0) {\n for (let i = 0; i < 256; i++) {\n lookupTable.push(i.toString(16).padStart(2, '0'));\n }\n }\n\n return lookupTable;\n };\n}\n\n/**\n * Function implementation of the {@link getPrecomputedHexValuesBuilder}\n * function.\n */\nconst getPrecomputedHexValues = getPrecomputedHexValuesBuilder();\n\n/**\n * Check if a value is a `Uint8Array`.\n *\n * @param value - The value to check.\n * @returns Whether the value is a `Uint8Array`.\n */\nexport function isBytes(value: unknown): value is Uint8Array {\n return value instanceof Uint8Array;\n}\n\n/**\n * Assert that a value is a `Uint8Array`.\n *\n * @param value - The value to check.\n * @throws If the value is not a `Uint8Array`.\n */\nexport function assertIsBytes(value: unknown): asserts value is Uint8Array {\n assert(isBytes(value), 'Value must be a Uint8Array.');\n}\n\n/**\n * Convert a `Uint8Array` to a hexadecimal string.\n *\n * @param bytes - The bytes to convert to a hexadecimal string.\n * @returns The hexadecimal string.\n */\nexport function bytesToHex(bytes: Uint8Array): Hex {\n assertIsBytes(bytes);\n\n if (bytes.length === 0) {\n return '0x';\n }\n\n const lookupTable = getPrecomputedHexValues();\n const hex = new Array(bytes.length);\n\n for (let i = 0; i < bytes.length; i++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n hex[i] = lookupTable[bytes[i]!];\n }\n\n return add0x(hex.join(''));\n}\n\n/**\n * Convert a `Uint8Array` to a `bigint`.\n *\n * To convert a `Uint8Array` to a `number` instead, use {@link bytesToNumber}.\n * To convert a two's complement encoded `Uint8Array` to a `bigint`, use\n * {@link bytesToSignedBigInt}.\n *\n * @param bytes - The bytes to convert to a `bigint`.\n * @returns The `bigint`.\n */\nexport function bytesToBigInt(bytes: Uint8Array): bigint {\n assertIsBytes(bytes);\n\n const hex = bytesToHex(bytes);\n return BigInt(hex);\n}\n\n/**\n * Convert a `Uint8Array` to a signed `bigint`. This assumes that the bytes are\n * encoded in two's complement.\n *\n * To convert a `Uint8Array` to an unsigned `bigint` instead, use\n * {@link bytesToBigInt}.\n *\n * @see https://en.wikipedia.org/wiki/Two%27s_complement\n * @param bytes - The bytes to convert to a signed `bigint`.\n * @returns The signed `bigint`.\n */\nexport function bytesToSignedBigInt(bytes: Uint8Array): bigint {\n assertIsBytes(bytes);\n\n let value = BigInt(0);\n for (const byte of bytes) {\n // eslint-disable-next-line no-bitwise\n value = (value << BigInt(8)) + BigInt(byte);\n }\n\n return BigInt.asIntN(bytes.length * 8, value);\n}\n\n/**\n * Convert a `Uint8Array` to a `number`.\n *\n * To convert a `Uint8Array` to a `bigint` instead, use {@link bytesToBigInt}.\n *\n * @param bytes - The bytes to convert to a number.\n * @returns The number.\n * @throws If the resulting number is not a safe integer.\n */\nexport function bytesToNumber(bytes: Uint8Array): number {\n assertIsBytes(bytes);\n\n const bigint = bytesToBigInt(bytes);\n\n assert(\n bigint <= BigInt(Number.MAX_SAFE_INTEGER),\n 'Number is not a safe integer. Use `bytesToBigInt` instead.',\n );\n\n return Number(bigint);\n}\n\n/**\n * Convert a UTF-8 encoded `Uint8Array` to a `string`.\n *\n * @param bytes - The bytes to convert to a string.\n * @returns The string.\n */\nexport function bytesToString(bytes: Uint8Array): string {\n assertIsBytes(bytes);\n\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * Convert a hexadecimal string to a `Uint8Array`. The string can optionally be\n * prefixed with `0x`. It accepts even and odd length strings.\n *\n * If the value is \"0x\", an empty `Uint8Array` is returned.\n *\n * @param value - The hexadecimal string to convert to bytes.\n * @returns The bytes as `Uint8Array`.\n */\nexport function hexToBytes(value: string): Uint8Array {\n // \"0x\" is often used as empty byte array.\n if (value?.toLowerCase?.() === '0x') {\n return new Uint8Array();\n }\n\n assertIsHexString(value);\n\n // Remove the `0x` prefix if it exists, and pad the string to have an even\n // number of characters.\n const strippedValue = remove0x(value).toLowerCase();\n const normalizedValue =\n strippedValue.length % 2 === 0 ? strippedValue : `0${strippedValue}`;\n const bytes = new Uint8Array(normalizedValue.length / 2);\n\n for (let i = 0; i < bytes.length; i++) {\n // While this is not the prettiest way to convert a hexadecimal string to a\n // `Uint8Array`, it is a lot faster than using `parseInt` to convert each\n // character.\n const c1 = normalizedValue.charCodeAt(i * 2);\n const c2 = normalizedValue.charCodeAt(i * 2 + 1);\n const n1 =\n c1 -\n (c1 < HEX_MAXIMUM_NUMBER_CHARACTER\n ? HEX_MINIMUM_NUMBER_CHARACTER\n : HEX_CHARACTER_OFFSET);\n const n2 =\n c2 -\n (c2 < HEX_MAXIMUM_NUMBER_CHARACTER\n ? HEX_MINIMUM_NUMBER_CHARACTER\n : HEX_CHARACTER_OFFSET);\n\n bytes[i] = n1 * 16 + n2;\n }\n\n return bytes;\n}\n\n/**\n * Convert a `bigint` to a `Uint8Array`.\n *\n * This assumes that the `bigint` is an unsigned integer. To convert a signed\n * `bigint` instead, use {@link signedBigIntToBytes}.\n *\n * @param value - The bigint to convert to bytes.\n * @returns The bytes as `Uint8Array`.\n */\nexport function bigIntToBytes(value: bigint): Uint8Array {\n assert(typeof value === 'bigint', 'Value must be a bigint.');\n assert(value >= BigInt(0), 'Value must be a non-negative bigint.');\n\n const hex = value.toString(16);\n return hexToBytes(hex);\n}\n\n/**\n * Check if a `bigint` fits in a certain number of bytes.\n *\n * @param value - The `bigint` to check.\n * @param bytes - The number of bytes.\n * @returns Whether the `bigint` fits in the number of bytes.\n */\nfunction bigIntFits(value: bigint, bytes: number): boolean {\n assert(bytes > 0);\n\n /* eslint-disable no-bitwise */\n const mask = value >> BigInt(31);\n return !(((~value & mask) + (value & ~mask)) >> BigInt(bytes * 8 + ~0));\n /* eslint-enable no-bitwise */\n}\n\n/**\n * Convert a signed `bigint` to a `Uint8Array`. This uses two's complement\n * encoding to represent negative numbers.\n *\n * To convert an unsigned `bigint` to a `Uint8Array` instead, use\n * {@link bigIntToBytes}.\n *\n * @see https://en.wikipedia.org/wiki/Two%27s_complement\n * @param value - The number to convert to bytes.\n * @param byteLength - The length of the resulting `Uint8Array`. If the number\n * is larger than the maximum value that can be represented by the given length,\n * an error is thrown.\n * @returns The bytes as `Uint8Array`.\n */\nexport function signedBigIntToBytes(\n value: bigint,\n byteLength: number,\n): Uint8Array {\n assert(typeof value === 'bigint', 'Value must be a bigint.');\n assert(typeof byteLength === 'number', 'Byte length must be a number.');\n assert(byteLength > 0, 'Byte length must be greater than 0.');\n assert(\n bigIntFits(value, byteLength),\n 'Byte length is too small to represent the given value.',\n );\n\n // ESLint doesn't like mutating function parameters, so to avoid having to\n // disable the rule, we create a new variable.\n let numberValue = value;\n const bytes = new Uint8Array(byteLength);\n\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Number(BigInt.asUintN(8, numberValue));\n // eslint-disable-next-line no-bitwise\n numberValue >>= BigInt(8);\n }\n\n return bytes.reverse();\n}\n\n/**\n * Convert a `number` to a `Uint8Array`.\n *\n * @param value - The number to convert to bytes.\n * @returns The bytes as `Uint8Array`.\n * @throws If the number is not a safe integer.\n */\nexport function numberToBytes(value: number): Uint8Array {\n assert(typeof value === 'number', 'Value must be a number.');\n assert(value >= 0, 'Value must be a non-negative number.');\n assert(\n Number.isSafeInteger(value),\n 'Value is not a safe integer. Use `bigIntToBytes` instead.',\n );\n\n const hex = value.toString(16);\n return hexToBytes(hex);\n}\n\n/**\n * Convert a `string` to a UTF-8 encoded `Uint8Array`.\n *\n * @param value - The string to convert to bytes.\n * @returns The bytes as `Uint8Array`.\n */\nexport function stringToBytes(value: string): Uint8Array {\n assert(typeof value === 'string', 'Value must be a string.');\n\n return new TextEncoder().encode(value);\n}\n\n/**\n * Convert a byte-like value to a `Uint8Array`. The value can be a `Uint8Array`,\n * a `bigint`, a `number`, or a `string`.\n *\n * This will attempt to guess the type of the value based on its type and\n * contents. For more control over the conversion, use the more specific\n * conversion functions, such as {@link hexToBytes} or {@link stringToBytes}.\n *\n * If the value is a `string`, and it is prefixed with `0x`, it will be\n * interpreted as a hexadecimal string. Otherwise, it will be interpreted as a\n * UTF-8 string. To convert a hexadecimal string to bytes without interpreting\n * it as a UTF-8 string, use {@link hexToBytes} instead.\n *\n * If the value is a `bigint`, it is assumed to be unsigned. To convert a signed\n * `bigint` to bytes, use {@link signedBigIntToBytes} instead.\n *\n * If the value is a `Uint8Array`, it will be returned as-is.\n *\n * @param value - The value to convert to bytes.\n * @returns The bytes as `Uint8Array`.\n */\nexport function valueToBytes(value: Bytes): Uint8Array {\n if (typeof value === 'bigint') {\n return bigIntToBytes(value);\n }\n\n if (typeof value === 'number') {\n return numberToBytes(value);\n }\n\n if (typeof value === 'string') {\n if (value.startsWith('0x')) {\n return hexToBytes(value);\n }\n\n return stringToBytes(value);\n }\n\n if (isBytes(value)) {\n return value;\n }\n\n throw new TypeError(`Unsupported value type: \"${typeof value}\".`);\n}\n\n/**\n * Concatenate multiple byte-like values into a single `Uint8Array`. The values\n * can be `Uint8Array`, `bigint`, `number`, or `string`. This uses\n * {@link valueToBytes} under the hood to convert each value to bytes. Refer to\n * the documentation of that function for more information.\n *\n * @param values - The values to concatenate.\n * @returns The concatenated bytes as `Uint8Array`.\n */\nexport function concatBytes(values: Bytes[]): Uint8Array {\n const normalizedValues = new Array(values.length);\n let byteLength = 0;\n\n for (let i = 0; i < values.length; i++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const value = valueToBytes(values[i]!);\n\n normalizedValues[i] = value;\n byteLength += value.length;\n }\n\n const bytes = new Uint8Array(byteLength);\n for (let i = 0, offset = 0; i < normalizedValues.length; i++) {\n // While we could simply spread the values into an array and use\n // `Uint8Array.from`, that is a lot slower than using `Uint8Array.set`.\n bytes.set(normalizedValues[i], offset);\n offset += normalizedValues[i].length;\n }\n\n return bytes;\n}\n"]}