UNPKG

@bsv/sdk

Version:

BSV Blockchain Software Development Kit

873 lines 29 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.minimallyEncode = exports.Reader = exports.Writer = exports.fromBase58Check = exports.toBase58Check = exports.toBase58 = exports.fromBase58 = exports.encode = exports.toUTF8 = exports.toArray = exports.toHex = exports.zero2 = void 0; exports.base64ToArray = base64ToArray; exports.toBase64 = toBase64; exports.verifyNotNull = verifyNotNull; exports.constantTimeEquals = constantTimeEquals; const BigNumber_js_1 = __importDefault(require("./BigNumber.js")); const Hash_js_1 = require("./Hash.js"); const hex_js_1 = require("./hex.js"); const BufferCtor = typeof globalThis !== 'undefined' ? globalThis.Buffer : undefined; const CAN_USE_BUFFER = BufferCtor != null && typeof BufferCtor.from === 'function'; /** * Prepends a '0' to an odd character length word to ensure it has an even number of characters. * @param {string} word - The input word. * @returns {string} - The word with a leading '0' if it's an odd character length; otherwise, the original word. */ const zero2 = (word) => { if (word.length % 2 === 1) { return '0' + word; } else { return word; } }; exports.zero2 = zero2; /** * Converts an array of numbers to a hexadecimal string representation. * @param {number[]} msg - The input array of numbers. * @returns {string} - The hexadecimal string representation of the input array. */ const HEX_DIGITS = '0123456789abcdef'; const HEX_BYTE_STRINGS = new Array(256); for (let i = 0; i < 256; i++) { HEX_BYTE_STRINGS[i] = HEX_DIGITS[(i >> 4) & 0xf] + HEX_DIGITS[i & 0xf]; } const toHex = (msg) => { if (CAN_USE_BUFFER) { return BufferCtor.from(msg).toString('hex'); } if (msg.length === 0) return ''; const out = new Array(msg.length); for (let i = 0; i < msg.length; i++) { out[i] = HEX_BYTE_STRINGS[msg[i] & 0xff]; } return out.join(''); }; exports.toHex = toHex; /** * Converts various message formats into an array of numbers. * Supports arrays, hexadecimal strings, base64 strings, and UTF-8 strings. * * @param {any} msg - The input message (array or string). * @param {('hex' | 'utf8' | 'base64')} enc - Specifies the string encoding, if applicable. * @returns {any[]} - Array representation of the input. */ const toArray = (msg, enc) => { if (Array.isArray(msg)) return msg.slice(); if (msg === undefined) return []; if (typeof msg !== 'string') { return Array.from(msg, (item) => item | 0); } switch (enc) { case 'hex': return hexToArray(msg); case 'base64': return base64ToArray(msg); default: return utf8ToArray(msg); } }; exports.toArray = toArray; const HEX_CHAR_TO_VALUE = new Int8Array(256).fill(-1); for (let i = 0; i < 10; i++) { HEX_CHAR_TO_VALUE[48 + i] = i; // '0'-'9' } for (let i = 0; i < 6; i++) { HEX_CHAR_TO_VALUE[65 + i] = 10 + i; // 'A'-'F' HEX_CHAR_TO_VALUE[97 + i] = 10 + i; // 'a'-'f' } const hexToArray = (msg) => { (0, hex_js_1.assertValidHex)(msg); const normalized = msg.length % 2 === 0 ? msg : '0' + msg; if (CAN_USE_BUFFER) { return Array.from(BufferCtor.from(normalized, 'hex')); } const out = new Array(normalized.length / 2); let o = 0; for (let i = 0; i < normalized.length; i += 2) { const hi = HEX_CHAR_TO_VALUE[normalized.charCodeAt(i)]; const lo = HEX_CHAR_TO_VALUE[normalized.charCodeAt(i + 1)]; out[o++] = (hi << 4) | lo; } return out; }; function base64ToArray(msg) { if (typeof msg !== 'string') { throw new TypeError('msg must be a string'); } // cleanse string let s = msg.trim().replace(/[\r\n\t\f\v ]+/g, ''); s = s.replace(/-/g, '+').replace(/_/g, '/'); // ensure padding is correct const padIndex = s.indexOf('='); if (padIndex !== -1) { const pad = s.slice(padIndex); if (!/^={1,2}$/.test(pad)) { throw new Error('Invalid base64 padding'); } if (s.slice(0, padIndex).includes('=')) { throw new Error('Invalid base64 padding'); } s = s.slice(0, padIndex); } // if (s.length % 4 === 1) // { // throw new Error("Invalid base64 length") // } const result = []; let bitBuffer = 0; let bitCount = 0; for (let i = 0; i < s.length; i++) { const c = s.charCodeAt(i); // using ascii map values rather than indexOf let v = -1; if (c >= 65 && c <= 90) { v = c - 65; // A-Z } else if (c >= 97 && c <= 122) { v = c - 97 + 26; // a-z } else if (c >= 48 && c <= 57) { v = c - 48 + 52; // 0-9 } else if (c === 43) { v = 62; // + } else if (c === 47) { v = 63; // / } else { throw new Error(`Invalid base64 character at index ${i}`); } bitBuffer = (bitBuffer << 6) | v; bitCount += 6; while (bitCount >= 8) { bitCount -= 8; result.push((bitBuffer >> bitCount) & 0xff); bitBuffer &= (1 << bitCount) - 1; } } // check for valid padding bits // if (bitCount !== 0 && bitBuffer !== 0) { // throw new Error("Invalid base64: non-zero padding bits") // } return result; } /** * Encodes a string into an array of bytes representing its UTF-8 encoding. * Any lone surrogates are replaced with the Unicode replacement character (U+FFFD). * * @param str - The string to encode. * @returns An array of numbers, each representing a byte in the UTF-8 encoded string. */ function utf8ToArray(str) { const result = []; for (let i = 0; i < str.length; i++) { const cp = str.codePointAt(i); if (cp === undefined) { // Should never be out of range. throw new Error(`Index out of range: ${i}`); } let codePoint = cp; if (codePoint > 0xFFFF) { // Valid surrogate pair => skip the next code unit because codePointAt // has already combined them into a single code point. i++; } else { // Check if codePoint is a lone (unpaired) high surrogate or low surrogate. if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { // Replace with the replacement character (U+FFFD). codePoint = 0xFFFD; } } // Encode according to the UTF-8 standard if (codePoint <= 0x7F) { result.push(codePoint); } else if (codePoint <= 0x7FF) { result.push(0xC0 | (codePoint >> 6), 0x80 | (codePoint & 0x3F)); } else if (codePoint <= 0xFFFF) { result.push(0xE0 | (codePoint >> 12), 0x80 | ((codePoint >> 6) & 0x3F), 0x80 | (codePoint & 0x3F)); } else { result.push(0xF0 | (codePoint >> 18), 0x80 | ((codePoint >> 12) & 0x3F), 0x80 | ((codePoint >> 6) & 0x3F), 0x80 | (codePoint & 0x3F)); } } return result; } /** * Converts an array of numbers to a UTF-8 encoded string. * @param {number[]} arr - The input array of numbers. * @returns {string} - The UTF-8 encoded string. */ const toUTF8 = (arr) => { let result = ''; const replacementChar = '\uFFFD'; for (let i = 0; i < arr.length; i++) { const byte1 = arr[i]; if (byte1 <= 0x7f) { result += String.fromCharCode(byte1); continue; } const emitReplacement = () => { result += replacementChar; }; if (byte1 >= 0xc0 && byte1 <= 0xdf) { if (i + 1 >= arr.length) { emitReplacement(); continue; } const byte2 = arr[i + 1]; if ((byte2 & 0xc0) !== 0x80) { emitReplacement(); i += 1; continue; } const codePoint = ((byte1 & 0x1f) << 6) | (byte2 & 0x3f); result += String.fromCharCode(codePoint); i += 1; continue; } if (byte1 >= 0xe0 && byte1 <= 0xef) { if (i + 2 >= arr.length) { emitReplacement(); continue; } const byte2 = arr[i + 1]; const byte3 = arr[i + 2]; if ((byte2 & 0xc0) !== 0x80 || (byte3 & 0xc0) !== 0x80) { emitReplacement(); i += 2; continue; } const codePoint = ((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f); result += String.fromCharCode(codePoint); i += 2; continue; } if (byte1 >= 0xf0 && byte1 <= 0xf7) { if (i + 3 >= arr.length) { emitReplacement(); continue; } const byte2 = arr[i + 1]; const byte3 = arr[i + 2]; const byte4 = arr[i + 3]; if ((byte2 & 0xc0) !== 0x80 || (byte3 & 0xc0) !== 0x80 || (byte4 & 0xc0) !== 0x80) { emitReplacement(); i += 3; continue; } const codePoint = ((byte1 & 0x07) << 18) | ((byte2 & 0x3f) << 12) | ((byte3 & 0x3f) << 6) | (byte4 & 0x3f); const offset = codePoint - 0x10000; const highSurrogate = 0xd800 + (offset >> 10); const lowSurrogate = 0xdc00 + (offset & 0x3ff); result += String.fromCharCode(highSurrogate, lowSurrogate); i += 3; continue; } emitReplacement(); } return result; }; exports.toUTF8 = toUTF8; /** * Encodes an array of numbers into a specified encoding ('hex' or 'utf8'). If no encoding is provided, returns the original array. * @param {number[]} arr - The input array of numbers. * @param {('hex' | 'utf8')} enc - The desired encoding. * @returns {string | number[]} - The encoded message as a string (for 'hex' and 'utf8') or the original array. */ const encode = (arr, enc) => { switch (enc) { case 'hex': return (0, exports.toHex)(arr); case 'utf8': return (0, exports.toUTF8)(arr); // If no encoding is provided, return the original array default: return arr; } }; exports.encode = encode; /** * Converts an array of bytes (each between 0 and 255) into a base64 encoded string. * * @param {number[]} byteArray - An array of numbers where each number is a byte (0-255). * @returns {string} The base64 encoded string. * * @example * const bytes = [72, 101, 108, 108, 111]; // Represents the string "Hello" * console.log(toBase64(bytes)); // Outputs: SGVsbG8= */ function toBase64(byteArray) { const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; let result = ''; let i; for (i = 0; i < byteArray.length; i += 3) { const byte1 = byteArray[i]; const byte2 = i + 1 < byteArray.length ? byteArray[i + 1] : 0; const byte3 = i + 2 < byteArray.length ? byteArray[i + 2] : 0; const encoded1 = byte1 >> 2; const encoded2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); const encoded3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6); const encoded4 = byte3 & 0x3f; result += base64Chars.charAt(encoded1) + base64Chars.charAt(encoded2); result += i + 1 < byteArray.length ? base64Chars.charAt(encoded3) : '='; result += i + 2 < byteArray.length ? base64Chars.charAt(encoded4) : '='; } return result; } const base58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; /** * Converts a string from base58 to a binary array * @param str - The string representation * @returns The binary representation */ const fromBase58 = (str) => { if (str === '' || typeof str !== 'string') { throw new Error(`Expected base58 string but got “${str}”`); } const match = str.match(/[IOl0]/gmu); if (match !== null) { throw new Error(`Invalid base58 character “${match.join('')}”`); } const lz = str.match(/^1+/gmu); const psz = (lz !== null) ? lz[0].length : 0; const size = ((str.length - psz) * (Math.log(58) / Math.log(256)) + 1) >>> 0; const uint8 = new Uint8Array([ ...new Uint8Array(psz), ...(str.match(/./gmu) ?? [] // ✅ Safe Fix: If null, use [] ) .map((i) => base58chars.indexOf(i)) .reduce((acc, i) => { acc = acc.map((j) => { const x = j * 58 + i; i = x >> 8; return x; }); return acc; }, new Uint8Array(size)) .reverse() .filter(((lastValue) => (value) => // @ts-expect-error (lastValue = lastValue || value))(false)) ]); return [...uint8]; }; exports.fromBase58 = fromBase58; /** * Converts a binary array into a base58 string * @param bin - The binary array to convert to base58 * @returns The base58 string representation */ const toBase58 = (bin) => { const base58Map = Array(256).fill(-1); for (let i = 0; i < base58chars.length; ++i) { base58Map[base58chars.charCodeAt(i)] = i; } const result = []; for (const byte of bin) { let carry = byte; for (let j = 0; j < result.length; ++j) { const x = (base58Map[result[j]] << 8) + carry; result[j] = base58chars.charCodeAt(x % 58); carry = (x / 58) | 0; } while (carry !== 0) { result.push(base58chars.charCodeAt(carry % 58)); carry = (carry / 58) | 0; } } for (const byte of bin) { if (byte !== 0) break; else result.push('1'.charCodeAt(0)); } result.reverse(); return String.fromCharCode(...result); }; exports.toBase58 = toBase58; /** * Converts a binary array into a base58check string with a checksum * @param bin - The binary array to convert to base58check * @returns The base58check string representation */ const toBase58Check = (bin, prefix = [0]) => { let hash = (0, Hash_js_1.hash256)([...prefix, ...bin]); hash = [...prefix, ...bin, ...hash.slice(0, 4)]; return (0, exports.toBase58)(hash); }; exports.toBase58Check = toBase58Check; /** * Converts a base58check string into a binary array after validating the checksum * @param str - The base58check string to convert to binary * @param enc - If hex, the return values will be hex strings, arrays of numbers otherwise * @param prefixLength - The length of the prefix. Optional, defaults to 1. * @returns The binary array representation */ const fromBase58Check = (str, enc, prefixLength = 1) => { const bin = (0, exports.fromBase58)(str); let prefix = bin.slice(0, prefixLength); let data = bin.slice(prefixLength, -4); let hash = [...prefix, ...data]; hash = (0, Hash_js_1.hash256)(hash); bin.slice(-4).forEach((check, index) => { if (check !== hash[index]) { throw new Error('Invalid checksum'); } }); if (enc === 'hex') { prefix = (0, exports.toHex)(prefix); data = (0, exports.toHex)(data); } return { prefix, data }; }; exports.fromBase58Check = fromBase58Check; class Writer { constructor(bufs) { this.bufs = bufs !== undefined ? bufs : []; this.length = 0; for (const b of this.bufs) this.length += b.length; } getLength() { return this.length; } toUint8Array() { const out = new Uint8Array(this.length); let offset = 0; for (const buf of this.bufs) { out.set(buf, offset); offset += buf.length; } return out; } toArray() { const totalLength = this.length; const ret = new Array(totalLength); let offset = 0; for (const buf of this.bufs) { if (buf instanceof Uint8Array) { for (let i = 0; i < buf.length; i++) { ret[offset++] = buf[i]; } } else { const arr = buf; for (let i = 0; i < arr.length; i++) { ret[offset++] = arr[i]; } } } return ret; } write(buf) { this.bufs.push(buf); this.length += buf.length; return this; } writeReverse(buf) { const buf2 = new Array(buf.length); for (let i = 0; i < buf2.length; i++) { buf2[i] = buf[buf.length - 1 - i]; } return this.write(buf2); } writeUInt8(n) { const buf = new Array(1); buf[0] = n & 0xff; this.write(buf); return this; } writeInt8(n) { const buf = new Array(1); buf[0] = n & 0xff; this.write(buf); return this; } writeUInt16BE(n) { const buf = [ (n >> 8) & 0xff, // shift right 8 bits to get the high byte n & 0xff // low byte is just the last 8 bits ]; return this.write(buf); } writeInt16BE(n) { return this.writeUInt16BE(n & 0xffff); // Mask with 0xFFFF to get the lower 16 bits } writeUInt16LE(n) { const buf = [ n & 0xff, // low byte is just the last 8 bits (n >> 8) & 0xff // shift right 8 bits to get the high byte ]; return this.write(buf); } writeInt16LE(n) { return this.writeUInt16LE(n & 0xffff); // Mask with 0xFFFF to get the lower 16 bits } writeUInt32BE(n) { const buf = [ (n >> 24) & 0xff, // highest byte (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff // lowest byte ]; return this.write(buf); } writeInt32BE(n) { return this.writeUInt32BE(n >>> 0); // Using unsigned right shift to handle negative numbers } writeUInt32LE(n) { const buf = [ n & 0xff, // lowest byte (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff // highest byte ]; return this.write(buf); } writeInt32LE(n) { return this.writeUInt32LE(n >>> 0); // Using unsigned right shift to handle negative numbers } writeUInt64BEBn(bn) { const buf = bn.toArray('be', 8); this.write(buf); return this; } writeUInt64LEBn(bn) { const buf = bn.toArray('be', 8); this.writeReverse(buf); return this; } writeUInt64LE(n) { const buf = new BigNumber_js_1.default(n).toArray('be', 8); this.writeReverse(buf); return this; } writeVarIntNum(n) { const buf = Writer.varIntNum(n); this.write(buf); return this; } writeVarIntBn(bn) { const buf = Writer.varIntBn(bn); this.write(buf); return this; } static varIntNum(n) { let buf; if (n < 0) { return this.varIntBn(new BigNumber_js_1.default(n)); } if (n < 253) { buf = [n]; // 1 byte } else if (n < 0x10000) { // 253 followed by the number in little-endian format buf = [ 253, // 0xfd n & 0xff, // low byte (n >> 8) & 0xff // high byte ]; } else if (n < 0x100000000) { // 254 followed by the number in little-endian format buf = [ 254, // 0xfe n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff ]; } else { // 255 followed by the number in little-endian format // Since JavaScript bitwise operations work on 32 bits, we need to handle 64-bit numbers in two parts const low = n & 0xffffffff; const high = Math.floor(n / 0x100000000) & 0xffffffff; buf = [ 255, // 0xff low & 0xff, (low >> 8) & 0xff, (low >> 16) & 0xff, (low >> 24) & 0xff, high & 0xff, (high >> 8) & 0xff, (high >> 16) & 0xff, (high >> 24) & 0xff ]; } return buf; } static varIntBn(bn) { let buf; if (bn.isNeg()) { bn = bn.add(OverflowUint64); // Adjust for negative numbers } if (bn.ltn(253)) { const n = bn.toNumber(); // No need for bitwise operation as the value is within a byte's range buf = [n]; } else if (bn.ltn(0x10000)) { const n = bn.toNumber(); // Value fits in a uint16 buf = [253, n & 0xff, (n >> 8) & 0xff]; } else if (bn.lt(new BigNumber_js_1.default(0x100000000))) { const n = bn.toNumber(); // Value fits in a uint32 buf = [ 254, n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff ]; } else { const bw = new Writer(); bw.writeUInt8(255); bw.writeUInt64LEBn(bn); buf = bw.toArray(); } return buf; } } exports.Writer = Writer; class Reader { constructor(bin = [], pos = 0) { this.bin = bin; this.pos = pos; this.length = bin.length; } eof() { return this.pos >= this.length; } read(len = this.length) { const start = this.pos; const end = this.pos + len; this.pos = end; return this.bin.slice(start, end); } readReverse(len = this.length) { const buf2 = new Array(len); for (let i = 0; i < len; i++) { buf2[i] = this.bin[this.pos + len - 1 - i]; } this.pos += len; return buf2; } readUInt8() { const val = this.bin[this.pos]; this.pos += 1; return val; } readInt8() { const val = this.bin[this.pos]; this.pos += 1; // If the sign bit is set, convert to negative value return (val & 0x80) !== 0 ? val - 0x100 : val; } readUInt16BE() { const val = (this.bin[this.pos] << 8) | this.bin[this.pos + 1]; this.pos += 2; return val; } readInt16BE() { const val = this.readUInt16BE(); // If the sign bit is set, convert to negative value return (val & 0x8000) !== 0 ? val - 0x10000 : val; } readUInt16LE() { const val = this.bin[this.pos] | (this.bin[this.pos + 1] << 8); this.pos += 2; return val; } readInt16LE() { const val = this.readUInt16LE(); // If the sign bit is set, convert to negative value const x = (val & 0x8000) !== 0 ? val - 0x10000 : val; return x; } readUInt32BE() { const val = this.bin[this.pos] * 0x1000000 + // Shift the first byte by 24 bits ((this.bin[this.pos + 1] << 16) | // Shift the second byte by 16 bits (this.bin[this.pos + 2] << 8) | // Shift the third byte by 8 bits this.bin[this.pos + 3]); // The fourth byte this.pos += 4; return val; } readInt32BE() { const val = this.readUInt32BE(); // If the sign bit is set, convert to negative value return (val & 0x80000000) !== 0 ? val - 0x100000000 : val; } readUInt32LE() { const val = (this.bin[this.pos] | (this.bin[this.pos + 1] << 8) | (this.bin[this.pos + 2] << 16) | (this.bin[this.pos + 3] << 24)) >>> 0; this.pos += 4; return val; } readInt32LE() { const val = this.readUInt32LE(); // Explicitly check if the sign bit is set and then convert to a negative value return (val & 0x80000000) !== 0 ? val - 0x100000000 : val; } readUInt64BEBn() { const bin = this.bin.slice(this.pos, this.pos + 8); const bn = new BigNumber_js_1.default(bin); this.pos = this.pos + 8; return bn; } readUInt64LEBn() { const bin = this.readReverse(8); const bn = new BigNumber_js_1.default(bin); return bn; } readInt64LEBn() { const bin = this.readReverse(8); let bn = new BigNumber_js_1.default(bin); if (bn.gte(OverflowInt64)) { bn = bn.sub(OverflowUint64); // Adjust for negative numbers } return bn; } readVarIntNum(signed = true) { const first = this.readUInt8(); let bn; switch (first) { case 0xfd: return this.readUInt16LE(); case 0xfe: return this.readUInt32LE(); case 0xff: bn = signed ? this.readInt64LEBn() : this.readUInt64LEBn(); if (bn.lte(new BigNumber_js_1.default(2).pow(new BigNumber_js_1.default(53)))) { return bn.toNumber(); } else { throw new Error('number too large to retain precision - use readVarIntBn'); } default: return first; } } readVarInt() { const first = this.bin[this.pos]; switch (first) { case 0xfd: return this.read(1 + 2); case 0xfe: return this.read(1 + 4); case 0xff: return this.read(1 + 8); default: return this.read(1); } } readVarIntBn() { const first = this.readUInt8(); switch (first) { case 0xfd: return new BigNumber_js_1.default(this.readUInt16LE()); case 0xfe: return new BigNumber_js_1.default(this.readUInt32LE()); case 0xff: return this.readUInt64LEBn(); default: return new BigNumber_js_1.default(first); } } } exports.Reader = Reader; const minimallyEncode = (buf) => { if (buf.length === 0) { return buf; } // If the last byte is not 0x00 or 0x80, we are minimally encoded. const last = buf[buf.length - 1]; if ((last & 0x7f) !== 0) { return buf; } // If the script is one byte long, then we have a zero, which encodes as an // empty array. if (buf.length === 1) { return []; } // If the next byte has it sign bit set, then we are minimaly encoded. if ((buf[buf.length - 2] & 0x80) !== 0) { return buf; } // We are not minimally encoded, we need to figure out how much to trim. for (let i = buf.length - 1; i > 0; i--) { // We found a non zero byte, time to encode. if (buf[i - 1] !== 0) { if ((buf[i - 1] & 0x80) !== 0) { // We found a byte with it sign bit set so we need one more // byte. buf[i] = last; return buf.slice(0, i + 1); } else { // the sign bit is clear, we can use it. buf[i - 1] |= last; return buf.slice(0, i); } } } // If we found the whole thing is zeros, then we have a zero. return []; }; exports.minimallyEncode = minimallyEncode; const OverflowInt64 = new BigNumber_js_1.default(2).pow(new BigNumber_js_1.default(63)); const OverflowUint64 = new BigNumber_js_1.default(2).pow(new BigNumber_js_1.default(64)); /** * Verifies that a value is not null or undefined, throwing an error if it is. * * @template T - The type of the value being verified * @param {T | undefined | null} value - The value to verify * @param {string} errorMessage - The error message to throw if the value is null or undefined * @returns {T} - The verified value * @throws {Error} - If the value is null or undefined * * @example * const myValue = verifyNotNull(someValue, 'someValue must be defined') */ function verifyNotNull(value, errorMessage = 'Expected a valid value, but got undefined or null.') { if (value == null) throw new Error(errorMessage); return value; } function constantTimeEquals(a, b) { if (a.length !== b.length) return false; let diff = 0; for (let i = 0; i < a.length; i++) { diff |= a[i] ^ b[i]; } return diff === 0; } //# sourceMappingURL=utils.js.map