UNPKG

@bsv/sdk

Version:

BSV Blockchain Software Development Kit

102 lines (90 loc) 2.96 kB
/** * Random number generator that works across modern JavaScript environments. * * This implementation uses the Web Crypto API which is available in: * - Node.js 6+ via require('crypto').randomBytes() * - Node.js 18+ via globalThis.crypto * - Modern browsers via globalThis.crypto, self.crypto, or window.crypto * - Web Workers and Service Workers via self.crypto * - Deno and Bun via globalThis.crypto * * @throws {Error} If no secure random number generator is available */ class Rand { _rand: (n: number) => number[] // ✅ Explicit function type getRandomValues (obj: any, n: number): number[] { const arr = new Uint8Array(n) obj.crypto.getRandomValues(arr) return Array.from(arr) } constructor () { const noRand = (): never => { throw new Error( 'No secure random number generator is available in this environment.' ) } this._rand = noRand // Assign the function // Try globalThis.crypto (works in Node.js 18+, modern browsers, and Deno) if (typeof globalThis !== 'undefined' && typeof (globalThis as any).crypto?.getRandomValues === 'function') { this._rand = (n) => { /* eslint-disable-next-line */ return this.getRandomValues(globalThis as any, n) } return } // Node.js fallback for versions < 18 if (typeof process !== 'undefined' && process.release?.name === 'node') { try { // eslint-disable-next-line @typescript-eslint/no-var-requires const crypto = require('crypto') if (typeof crypto.randomBytes === 'function') { this._rand = (n) => { return Array.from(crypto.randomBytes(n)) } return } } catch (e) { // crypto module not available, continue to other checks } } // Try self.crypto (Web Workers and Service Workers) if (typeof self !== 'undefined' && typeof self.crypto?.getRandomValues === 'function') { this._rand = (n) => { /* eslint-disable-next-line */ return this.getRandomValues(self as any, n) } return } // Try window.crypto (browsers) if (typeof window !== 'undefined' && typeof (window as any).crypto?.getRandomValues === 'function') { this._rand = (n) => { /* eslint-disable-next-line */ return this.getRandomValues(window as any, n) } return } // No crypto available this._rand = noRand } generate (len: number): number[] { return this._rand(len) } } let ayn: Rand | null = null /** * Generates a sequence of pseudo-random bytes with the given length. * * @param len - The number of bytes to generate * * @returns The generated bytes * * @example * import Random from '@bsv/sdk/primitives/Random' * const bytes = Random(32) // Produces 32 random bytes */ export default (len: number): number[] => { if (ayn == null) { ayn = new Rand() } return ayn.generate(len) }