140 lines
3.7 KiB
TypeScript
140 lines
3.7 KiB
TypeScript
/**
|
|
* 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<void>;
|
|
create_keyspace: (keyspace: string, password: string) => Promise<void>;
|
|
lock_session: () => void;
|
|
is_unlocked: () => boolean;
|
|
|
|
// Keypair management
|
|
add_keypair: (key_type: string | undefined, metadata: string | undefined) => Promise<string>;
|
|
list_keypairs: () => Promise<string>;
|
|
select_keypair: (key_id: string) => Promise<void>;
|
|
current_keypair_metadata: () => Promise<any>;
|
|
current_keypair_public_key: () => Promise<Uint8Array>;
|
|
|
|
// Cryptographic operations
|
|
sign: (message: Uint8Array) => Promise<string>;
|
|
verify: (message: Uint8Array, signature: string) => Promise<boolean>;
|
|
encrypt_data: (data: Uint8Array) => Promise<Uint8Array>;
|
|
decrypt_data: (encrypted: Uint8Array) => Promise<Uint8Array>;
|
|
|
|
// Rhai scripting
|
|
init_rhai_env: () => void;
|
|
run_rhai: (script: string) => Promise<string>;
|
|
}
|
|
|
|
// Global reference to the WASM module
|
|
let wasmModule: WasmModule | null = null;
|
|
let isInitializing = false;
|
|
let initPromise: Promise<void> | null = null;
|
|
|
|
/**
|
|
* Initialize the WASM module
|
|
* This should be called before any other WASM functions
|
|
*/
|
|
export const initWasm = async (): Promise<void> => {
|
|
if (wasmModule) {
|
|
return Promise.resolve(); // Already initialized
|
|
}
|
|
|
|
if (isInitializing && initPromise) {
|
|
return initPromise; // Already initializing
|
|
}
|
|
|
|
isInitializing = true;
|
|
|
|
initPromise = new Promise<void>(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<WasmModule> => {
|
|
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('');
|
|
};
|