/** * WASM Helper for Hero Vault Extension * * This module handles loading and initializing the WASM module, * and provides a typed interface to the WASM functions. */ // Import types for TypeScript interface WasmModule { // Session management init_session: (keyspace: string, password: string) => Promise; create_keyspace: (keyspace: string, password: string) => Promise; lock_session: () => void; is_unlocked: () => boolean; // Keypair management add_keypair: (key_type: string | undefined, metadata: string | undefined) => Promise; list_keypairs: () => Promise; select_keypair: (key_id: string) => Promise; current_keypair_metadata: () => Promise; current_keypair_public_key: () => Promise; // Cryptographic operations sign: (message: Uint8Array) => Promise; verify: (message: Uint8Array, signature: string) => Promise; encrypt_data: (data: Uint8Array) => Promise; decrypt_data: (encrypted: Uint8Array) => Promise; // Rhai scripting init_rhai_env: () => void; run_rhai: (script: string) => Promise; } // Global reference to the WASM module let wasmModule: WasmModule | null = null; let isInitializing = false; let initPromise: Promise | null = null; /** * Initialize the WASM module * This should be called before any other WASM functions */ export const initWasm = async (): Promise => { if (wasmModule) { return Promise.resolve(); // Already initialized } if (isInitializing && initPromise) { return initPromise; // Already initializing } isInitializing = true; initPromise = new Promise(async (resolve, reject) => { try { try { // Import the WASM module // Use a relative path that will be resolved by Vite during build const wasmImport = await import('../../public/wasm/wasm_app.js'); // Initialize the WASM module await wasmImport.default(); // Store the WASM module globally wasmModule = wasmImport as unknown as WasmModule; console.log('WASM module initialized successfully'); resolve(); } catch (error) { console.error('Failed to initialize WASM module:', error); reject(error); } } finally { isInitializing = false; } }); return initPromise; }; /** * Get the WASM module * This will initialize the module if it hasn't been initialized yet */ export const getWasmModule = async (): Promise => { if (!wasmModule) { await initWasm(); } if (!wasmModule) { throw new Error('WASM module failed to initialize'); } return wasmModule; }; /** * Check if the WASM module is initialized */ export const isWasmInitialized = (): boolean => { return wasmModule !== null; }; /** * Helper to convert string to Uint8Array */ export const stringToUint8Array = (str: string): Uint8Array => { const encoder = new TextEncoder(); return encoder.encode(str); }; /** * Helper to convert Uint8Array to string */ export const uint8ArrayToString = (array: Uint8Array): string => { const decoder = new TextDecoder(); return decoder.decode(array); }; /** * Helper to convert hex string to Uint8Array */ export const hexToUint8Array = (hex: string): Uint8Array => { const bytes = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i += 2) { bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16); } return bytes; }; /** * Helper to convert Uint8Array to hex string */ export const uint8ArrayToHex = (array: Uint8Array): string => { return Array.from(array) .map(b => b.toString(16).padStart(2, '0')) .join(''); };