UNPKG

@metamask/utils

Version:

Various JavaScript/TypeScript utilities of wide relevance to the MetaMask codebase

155 lines 5.4 kB
import { bigint, coerce, create, instance, number, string, StructError, union } from "@metamask/superstruct"; import { assert } from "./assert.mjs"; import { bytesToHex, hexToBytes } from "./bytes.mjs"; import { StrictHexStruct } from "./hex.mjs"; const NumberLikeStruct = union([number(), bigint(), string(), StrictHexStruct]); const NumberCoercer = coerce(number(), NumberLikeStruct, Number); const BigIntCoercer = coerce(bigint(), NumberLikeStruct, BigInt); const BytesLikeStruct = union([StrictHexStruct, instance(Uint8Array)]); const BytesCoercer = coerce(instance(Uint8Array), union([StrictHexStruct]), hexToBytes); const HexCoercer = coerce(StrictHexStruct, instance(Uint8Array), bytesToHex); /** * Create a number from a number-like value. * * - If the value is a number, it is returned as-is. * - If the value is a `bigint`, it is converted to a number. * - If the value is a string, it is interpreted as a decimal number. * - If the value is a hex string (i.e., it starts with "0x"), it is * interpreted as a hexadecimal number. * * This validates that the value is a number-like value, and that the resulting * number is not `NaN` or `Infinity`. * * @example * ```typescript * const value = createNumber('0x010203'); * console.log(value); // 66051 * * const otherValue = createNumber(123n); * console.log(otherValue); // 123 * ``` * @param value - The value to create the number from. * @returns The created number. * @throws If the value is not a number-like value, or if the resulting number * is `NaN` or `Infinity`. */ export function createNumber(value) { try { const result = create(value, NumberCoercer); assert(Number.isFinite(result), `Expected a number-like value, got "${value}".`); return result; } catch (error) { if (error instanceof StructError) { throw new Error(`Expected a number-like value, got "${value}".`); } /* istanbul ignore next */ throw error; } } /** * Create a `bigint` from a number-like value. * * - If the value is a number, it is converted to a `bigint`. * - If the value is a `bigint`, it is returned as-is. * - If the value is a string, it is interpreted as a decimal number and * converted to a `bigint`. * - If the value is a hex string (i.e., it starts with "0x"), it is * interpreted as a hexadecimal number and converted to a `bigint`. * * @example * ```typescript * const value = createBigInt('0x010203'); * console.log(value); // 16909060n * * const otherValue = createBigInt(123); * console.log(otherValue); // 123n * ``` * @param value - The value to create the bigint from. * @returns The created bigint. * @throws If the value is not a number-like value. */ export function createBigInt(value) { try { // The `BigInt` constructor throws if the value is not a number-like value. // There is no need to validate the value manually. return create(value, BigIntCoercer); } catch (error) { if (error instanceof StructError) { throw new Error(`Expected a number-like value, got "${String(error.value)}".`); } /* istanbul ignore next */ throw error; } } /** * Create a byte array from a bytes-like value. * * - If the value is a byte array, it is returned as-is. * - If the value is a hex string (i.e., it starts with "0x"), it is interpreted * as a hexadecimal number and converted to a byte array. * * @example * ```typescript * const value = createBytes('0x010203'); * console.log(value); // Uint8Array [ 1, 2, 3 ] * * const otherValue = createBytes('0x010203'); * console.log(otherValue); // Uint8Array [ 1, 2, 3 ] * ``` * @param value - The value to create the byte array from. * @returns The created byte array. * @throws If the value is not a bytes-like value. */ export function createBytes(value) { if (typeof value === 'string' && value.toLowerCase() === '0x') { return new Uint8Array(); } try { return create(value, BytesCoercer); } catch (error) { if (error instanceof StructError) { throw new Error(`Expected a bytes-like value, got "${String(error.value)}".`); } /* istanbul ignore next */ throw error; } } /** * Create a hexadecimal string from a bytes-like value. * * - If the value is a hex string (i.e., it starts with "0x"), it is returned * as-is. * - If the value is a `Uint8Array`, it is converted to a hex string. * * @example * ```typescript * const value = createHex(new Uint8Array([1, 2, 3])); * console.log(value); // '0x010203' * * const otherValue = createHex('0x010203'); * console.log(otherValue); // '0x010203' * ``` * @param value - The value to create the hex string from. * @returns The created hex string. * @throws If the value is not a bytes-like value. */ export function createHex(value) { if ((value instanceof Uint8Array && value.length === 0) || (typeof value === 'string' && value.toLowerCase() === '0x')) { return '0x'; } try { return create(value, HexCoercer); } catch (error) { if (error instanceof StructError) { throw new Error(`Expected a bytes-like value, got "${String(error.value)}".`); } /* istanbul ignore next */ throw error; } } //# sourceMappingURL=coercers.mjs.map