diff --git a/Makefile b/Makefile index 1b769f9..887930e 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,16 @@ build-wasm-app: # Build everything: wasm, copy, then extension build-extension-all: build-wasm-app - cp wasm_app/pkg/wasm_app.js extension/public/wasm/wasm_app.js - cp wasm_app/pkg/wasm_app_bg.wasm extension/public/wasm/wasm_app_bg.wasm cd extension && npm run build + +# Build everything: wasm, copy, then extension +build-vault-browser-ext: + cd wasm_app && wasm-pack build --target web --out-dir ../vault_browser_ext/wasm_app/pkg + cp vault_browser_ext/wasm_app/pkg/wasm_app.js vault_browser_ext/public/wasm/ + cp vault_browser_ext/wasm_app/pkg/wasm_app_bg.wasm vault_browser_ext/public/wasm/ + cd vault_browser_ext && npm install && npm run build + cp vault_browser_ext/manifest.json vault_browser_ext/dist/ + cp vault_browser_ext/*.png vault_browser_ext/dist/ + mkdir -p vault_browser_ext/dist/src + cp vault_browser_ext/sandbox.html vault_browser_ext/dist/ + cp vault_browser_ext/sandbox.js vault_browser_ext/dist/ \ No newline at end of file diff --git a/evm_client/Cargo.toml b/evm_client/Cargo.toml index 654fc23..5510f66 100644 --- a/evm_client/Cargo.toml +++ b/evm_client/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" path = "src/lib.rs" [dependencies] +instant = { version = "0.1", features = ["wasm-bindgen"] } # Only universal/core dependencies here tokio = { version = "1.37", features = ["rt", "macros"] } diff --git a/kvstore/Cargo.toml b/kvstore/Cargo.toml index 9ad7ee4..6c7f796 100644 --- a/kvstore/Cargo.toml +++ b/kvstore/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" path = "src/lib.rs" [dependencies] +instant = { version = "0.1", features = ["wasm-bindgen"] } tokio = { version = "1.37", features = ["rt", "macros"] } async-trait = "0.1" diff --git a/vault/Cargo.toml b/vault/Cargo.toml index 9c9739c..c126cf5 100644 --- a/vault/Cargo.toml +++ b/vault/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" path = "src/lib.rs" [dependencies] +instant = { version = "0.1", features = ["wasm-bindgen"] } once_cell = "1.18" tokio = { version = "1.37", features = ["rt", "macros"] } kvstore = { path = "../kvstore" } diff --git a/vault/src/session.rs b/vault/src/session.rs index d1ecc9b..7003ae9 100644 --- a/vault/src/session.rs +++ b/vault/src/session.rs @@ -9,6 +9,8 @@ use zeroize::Zeroize; /// SessionManager: Ergonomic, stateful wrapper over the Vault stateless API. #[cfg(not(target_arch = "wasm32"))] pub struct SessionManager { + // ... existing fields + vault: Vault, unlocked_keyspace: Option<(String, Vec, KeyspaceData)>, // (name, password, data) current_keypair: Option, @@ -38,7 +40,12 @@ impl SessionManager { } } - pub async fn create_keyspace(&mut self, name: &str, password: &[u8], tags: Option>) -> Result<(), VaultError> { + pub async fn create_keyspace( + &mut self, + name: &str, + password: &[u8], + tags: Option>, + ) -> Result<(), VaultError> { self.vault.create_keyspace(name, password, tags).await?; self.unlock_keyspace(name, password).await } @@ -90,12 +97,34 @@ impl SessionManager { self.unlocked_keyspace.as_ref().map(|(_, _, data)| data) } + /// Returns the name of the currently unlocked keyspace, if any. + pub fn current_keyspace_name(&self) -> Option<&str> { + self.unlocked_keyspace + .as_ref() + .map(|(name, _, _)| name.as_str()) + } + pub fn current_keypair(&self) -> Option<&KeyEntry> { let keyspace = self.current_keyspace()?; let key_id = self.current_keypair.as_ref()?; keyspace.keypairs.iter().find(|k| &k.id == key_id) } + /// Returns the metadata of the current selected keypair, if any. + pub fn current_keypair_metadata(&self) -> Option { + self.current_keypair().and_then(|k| k.metadata.clone()) + } + + /// Returns the public key of the current selected keypair, if any. + pub fn current_keypair_public_key(&self) -> Option> { + self.current_keypair().map(|k| k.public_key.clone()) + } + + /// Returns true if a keyspace is currently unlocked. + pub fn is_unlocked(&self) -> bool { + self.unlocked_keyspace.is_some() + } + pub async fn sign(&self, message: &[u8]) -> Result, VaultError> { let (name, password, _) = self .unlocked_keyspace @@ -137,7 +166,12 @@ impl SessionManager { } } - pub async fn create_keyspace(&mut self, name: &str, password: &[u8], tags: Option>) -> Result<(), VaultError> { + pub async fn create_keyspace( + &mut self, + name: &str, + password: &[u8], + tags: Option>, + ) -> Result<(), VaultError> { self.vault.create_keyspace(name, password, tags).await?; self.unlock_keyspace(name, password).await } @@ -189,12 +223,34 @@ impl SessionManager { self.unlocked_keyspace.as_ref().map(|(_, _, data)| data) } + /// Returns the name of the currently unlocked keyspace, if any. + pub fn current_keyspace_name(&self) -> Option<&str> { + self.unlocked_keyspace + .as_ref() + .map(|(name, _, _)| name.as_str()) + } + pub fn current_keypair(&self) -> Option<&KeyEntry> { let keyspace = self.current_keyspace()?; let key_id = self.current_keypair.as_ref()?; keyspace.keypairs.iter().find(|k| &k.id == key_id) } + /// Returns the metadata of the current selected keypair, if any. + pub fn current_keypair_metadata(&self) -> Option { + self.current_keypair().and_then(|k| k.metadata.clone()) + } + + /// Returns the public key of the current selected keypair, if any. + pub fn current_keypair_public_key(&self) -> Option> { + self.current_keypair().map(|k| k.public_key.clone()) + } + + /// Returns true if a keyspace is currently unlocked. + pub fn is_unlocked(&self) -> bool { + self.unlocked_keyspace.is_some() + } + pub async fn sign(&self, message: &[u8]) -> Result, VaultError> { let (name, password, _) = self .unlocked_keyspace diff --git a/wasm_app/Cargo.toml b/wasm_app/Cargo.toml index f055212..20aa6cb 100644 --- a/wasm_app/Cargo.toml +++ b/wasm_app/Cargo.toml @@ -7,7 +7,9 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] +instant = { version = "0.1", features = ["wasm-bindgen"] } web-sys = { version = "0.3", features = ["console"] } +js-sys = "0.3" kvstore = { path = "../kvstore" } hex = "0.4" wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } diff --git a/wasm_app/src/vault_bindings.rs b/wasm_app/src/vault_bindings.rs index 38aa51b..365aee7 100644 --- a/wasm_app/src/vault_bindings.rs +++ b/wasm_app/src/vault_bindings.rs @@ -9,6 +9,7 @@ use vault::rhai_bindings as vault_rhai_bindings; use vault::session::SessionManager; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; +use js_sys::Uint8Array; thread_local! { static ENGINE: Lazy> = Lazy::new(|| RefCell::new(Engine::new())); @@ -21,6 +22,34 @@ pub use vault::session_singleton::SESSION_MANAGER; // Session Lifecycle // ===================== +/// Create and unlock a new keyspace with the given name and password +#[wasm_bindgen] +pub async fn create_keyspace(keyspace: &str, password: &str) -> Result<(), JsValue> { + let keyspace = keyspace.to_string(); + let password_vec = password.as_bytes().to_vec(); + match WasmStore::open("vault").await { + Ok(store) => { + let vault = vault::Vault::new(store); + let mut manager = SessionManager::new(vault); + match manager.create_keyspace(&keyspace, &password_vec, None).await { + Ok(_) => { + SESSION_MANAGER.with(|cell| cell.replace(Some(manager))); + } + Err(e) => { + web_sys::console::error_1(&format!("Failed to create keyspace: {e}").into()); + return Err(JsValue::from_str(&format!("Failed to create keyspace: {e}"))); + } + } + } + Err(e) => { + web_sys::console::error_1(&format!("Failed to open WasmStore: {e}").into()); + return Err(JsValue::from_str(&format!("Failed to open WasmStore: {e}"))); + } + } + SESSION_PASSWORD.with(|cell| cell.replace(Some(password.as_bytes().to_vec()))); + Ok(()) +} + /// Initialize session with keyspace and password #[wasm_bindgen] pub async fn init_session(keyspace: &str, password: &str) -> Result<(), JsValue> { @@ -61,6 +90,36 @@ pub fn lock_session() { // Keypair Management // ===================== +/// Get metadata of the currently selected keypair +#[wasm_bindgen] +pub fn current_keypair_metadata() -> Result { + SESSION_MANAGER.with(|cell| { + cell.borrow().as_ref() + .and_then(|session| session.current_keypair_metadata()) + .map(|meta| wasm_bindgen::JsValue::from_serde(&meta).unwrap()) + .ok_or_else(|| JsValue::from_str("No keypair selected or no keyspace unlocked")) + }) +} + +/// Get public key of the currently selected keypair as Uint8Array +#[wasm_bindgen] +pub fn current_keypair_public_key() -> Result { + SESSION_MANAGER.with(|cell| { + cell.borrow().as_ref() + .and_then(|session| session.current_keypair_public_key()) + .map(|pk| js_sys::Uint8Array::from(pk.as_slice()).into()) + .ok_or_else(|| JsValue::from_str("No keypair selected or no keyspace unlocked")) + }) +} + +/// Returns true if a keyspace is currently unlocked +#[wasm_bindgen] +pub fn is_unlocked() -> bool { + SESSION_MANAGER.with(|cell| { + cell.borrow().as_ref().map(|session| session.is_unlocked()).unwrap_or(false) + }) +} + /// Get all keypairs from the current session /// Returns an array of keypair objects with id, type, and metadata // #[wasm_bindgen] @@ -118,18 +177,12 @@ pub async fn add_keypair( let password = SESSION_PASSWORD .with(|pw| pw.borrow().clone()) .ok_or_else(|| JsValue::from_str("Session password not set"))?; - let (keyspace_name, session_exists) = SESSION_MANAGER.with(|cell| { - if let Some(ref session) = cell.borrow().as_ref() { - let keyspace_name = session.current_keyspace().map(|_| "".to_string()); // TODO: replace with actual keyspace name if available; - (keyspace_name, true) - } else { - (None, false) - } + let keyspace_name = SESSION_MANAGER.with(|cell| { + cell.borrow().as_ref().and_then(|session| { + session.current_keyspace_name().map(|name| name.to_string()) + }) }); let keyspace_name = keyspace_name.ok_or_else(|| JsValue::from_str("No keyspace selected"))?; - if !session_exists { - return Err(JsValue::from_str("Session not initialized")); - } let key_type = key_type .as_deref() .map(|s| match s { @@ -153,6 +206,9 @@ pub async fn add_keypair( .add_keypair(&keyspace_name, &password, Some(key_type), metadata) .await .map_err(|e| JsValue::from_str(&format!("add_keypair error: {e}")))?; + // Refresh in-memory keyspace data so list_keypairs reflects the new keypair immediately + session.unlock_keyspace(&keyspace_name, &password).await + .map_err(|e| JsValue::from_str(&format!("refresh keyspace after add_keypair error: {e}")))?; // Put session back SESSION_MANAGER.with(|cell| *cell.borrow_mut() = Some(session_opt.take().unwrap())); Ok(JsValue::from_str(&key_id)) diff --git a/wasm_console_demo/index.html b/wasm_console_demo/index.html new file mode 100644 index 0000000..689551d --- /dev/null +++ b/wasm_console_demo/index.html @@ -0,0 +1,17 @@ + + + + + WASM App Demo + + +

WASM App Demo

+ + + \ No newline at end of file diff --git a/wasm_console_demo/main.js b/wasm_console_demo/main.js new file mode 100644 index 0000000..b7574c3 --- /dev/null +++ b/wasm_console_demo/main.js @@ -0,0 +1,13 @@ +// Minimal loader for the vault WASM module for console interaction +// Adjust the module path if needed (this assumes the default wasm-pack output in the parent dir) +import init, * as vault from './wasm_app.js'; + +window.vault = null; + +init().then(() => { + window.vault = vault; + console.log('Vault WASM module loaded. Use window.vault.() in the console.'); +}); + +// Optional: Helper to convert Uint8Array to hex +window.toHex = arr => Array.from(new Uint8Array(arr)).map(b => b.toString(16).padStart(2, '0')).join(''); diff --git a/wasm_console_demo/package.json b/wasm_console_demo/package.json new file mode 100644 index 0000000..cc6f3b5 --- /dev/null +++ b/wasm_console_demo/package.json @@ -0,0 +1,15 @@ +{ + "name": "wasm_app", + "type": "module", + "version": "0.1.0", + "files": [ + "wasm_app_bg.wasm", + "wasm_app.js", + "wasm_app.d.ts" + ], + "main": "wasm_app.js", + "types": "wasm_app.d.ts", + "sideEffects": [ + "./snippets/*" + ] +} \ No newline at end of file diff --git a/wasm_console_demo/wasm_app.d.ts b/wasm_console_demo/wasm_app.d.ts new file mode 100644 index 0000000..93458ca --- /dev/null +++ b/wasm_console_demo/wasm_app.d.ts @@ -0,0 +1,103 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Initialize the scripting environment (must be called before run_rhai) + */ +export function init_rhai_env(): void; +/** + * Securely run a Rhai script in the extension context (must be called only after user approval) + */ +export function run_rhai(script: string): any; +/** + * Create and unlock a new keyspace with the given name and password + */ +export function create_keyspace(keyspace: string, password: string): Promise; +/** + * Initialize session with keyspace and password + */ +export function init_session(keyspace: string, password: string): Promise; +/** + * Lock the session (zeroize password and session) + */ +export function lock_session(): void; +/** + * Get metadata of the currently selected keypair + */ +export function current_keypair_metadata(): any; +/** + * Get public key of the currently selected keypair as Uint8Array + */ +export function current_keypair_public_key(): any; +/** + * Returns true if a keyspace is currently unlocked + */ +export function is_unlocked(): boolean; +/** + * Get all keypairs from the current session + * Returns an array of keypair objects with id, type, and metadata + * Select keypair for the session + */ +export function select_keypair(key_id: string): void; +/** + * List keypairs in the current session's keyspace + */ +export function list_keypairs(): Promise; +/** + * Add a keypair to the current keyspace + */ +export function add_keypair(key_type?: string | null, metadata?: string | null): Promise; +/** + * Sign message with current session + */ +export function sign(message: Uint8Array): Promise; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly init_rhai_env: () => void; + readonly run_rhai: (a: number, b: number) => [number, number, number]; + readonly create_keyspace: (a: number, b: number, c: number, d: number) => any; + readonly init_session: (a: number, b: number, c: number, d: number) => any; + readonly lock_session: () => void; + readonly current_keypair_metadata: () => [number, number, number]; + readonly current_keypair_public_key: () => [number, number, number]; + readonly is_unlocked: () => number; + readonly select_keypair: (a: number, b: number) => [number, number]; + readonly list_keypairs: () => any; + readonly add_keypair: (a: number, b: number, c: number, d: number) => any; + readonly sign: (a: number, b: number) => any; + readonly __wbindgen_exn_store: (a: number) => void; + readonly __externref_table_alloc: () => number; + readonly __wbindgen_export_2: WebAssembly.Table; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_export_5: WebAssembly.Table; + readonly __externref_table_dealloc: (a: number) => void; + readonly closure89_externref_shim: (a: number, b: number, c: any) => void; + readonly closure133_externref_shim: (a: number, b: number, c: any) => void; + readonly closure188_externref_shim: (a: number, b: number, c: any) => void; + readonly closure1847_externref_shim: (a: number, b: number, c: any, d: any) => void; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. +* +* @returns {InitOutput} +*/ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. +* +* @returns {Promise} +*/ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/wasm_console_demo/wasm_app.js b/wasm_console_demo/wasm_app.js new file mode 100644 index 0000000..5583e35 --- /dev/null +++ b/wasm_console_demo/wasm_app.js @@ -0,0 +1,822 @@ +let wasm; + +function addToExternrefTable0(obj) { + const idx = wasm.__externref_table_alloc(); + wasm.__wbindgen_export_2.set(idx, obj); + return idx; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + const idx = addToExternrefTable0(e); + wasm.__wbindgen_exn_store(idx); + } +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8ArrayMemory0 = null; + +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +let cachedDataViewMemory0 = null; + +function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; +} + +const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(state => { + wasm.__wbindgen_export_5.get(state.dtor)(state.a, state.b) +}); + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_5.get(state.dtor)(a, state.b); + CLOSURE_DTORS.unregister(state); + } else { + state.a = a; + } + } + }; + real.original = state; + CLOSURE_DTORS.register(real, state, state); + return real; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches && builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} +/** + * Initialize the scripting environment (must be called before run_rhai) + */ +export function init_rhai_env() { + wasm.init_rhai_env(); +} + +function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_export_2.get(idx); + wasm.__externref_table_dealloc(idx); + return value; +} +/** + * Securely run a Rhai script in the extension context (must be called only after user approval) + * @param {string} script + * @returns {any} + */ +export function run_rhai(script) { + const ptr0 = passStringToWasm0(script, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.run_rhai(ptr0, len0); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return takeFromExternrefTable0(ret[0]); +} + +/** + * Create and unlock a new keyspace with the given name and password + * @param {string} keyspace + * @param {string} password + * @returns {Promise} + */ +export function create_keyspace(keyspace, password) { + const ptr0 = passStringToWasm0(keyspace, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.create_keyspace(ptr0, len0, ptr1, len1); + return ret; +} + +/** + * Initialize session with keyspace and password + * @param {string} keyspace + * @param {string} password + * @returns {Promise} + */ +export function init_session(keyspace, password) { + const ptr0 = passStringToWasm0(keyspace, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.init_session(ptr0, len0, ptr1, len1); + return ret; +} + +/** + * Lock the session (zeroize password and session) + */ +export function lock_session() { + wasm.lock_session(); +} + +/** + * Get metadata of the currently selected keypair + * @returns {any} + */ +export function current_keypair_metadata() { + const ret = wasm.current_keypair_metadata(); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return takeFromExternrefTable0(ret[0]); +} + +/** + * Get public key of the currently selected keypair as Uint8Array + * @returns {any} + */ +export function current_keypair_public_key() { + const ret = wasm.current_keypair_public_key(); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return takeFromExternrefTable0(ret[0]); +} + +/** + * Returns true if a keyspace is currently unlocked + * @returns {boolean} + */ +export function is_unlocked() { + const ret = wasm.is_unlocked(); + return ret !== 0; +} + +/** + * Get all keypairs from the current session + * Returns an array of keypair objects with id, type, and metadata + * Select keypair for the session + * @param {string} key_id + */ +export function select_keypair(key_id) { + const ptr0 = passStringToWasm0(key_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.select_keypair(ptr0, len0); + if (ret[1]) { + throw takeFromExternrefTable0(ret[0]); + } +} + +/** + * List keypairs in the current session's keyspace + * @returns {Promise} + */ +export function list_keypairs() { + const ret = wasm.list_keypairs(); + return ret; +} + +/** + * Add a keypair to the current keyspace + * @param {string | null} [key_type] + * @param {string | null} [metadata] + * @returns {Promise} + */ +export function add_keypair(key_type, metadata) { + var ptr0 = isLikeNone(key_type) ? 0 : passStringToWasm0(key_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len0 = WASM_VECTOR_LEN; + var ptr1 = isLikeNone(metadata) ? 0 : passStringToWasm0(metadata, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + const ret = wasm.add_keypair(ptr0, len0, ptr1, len1); + return ret; +} + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} +/** + * Sign message with current session + * @param {Uint8Array} message + * @returns {Promise} + */ +export function sign(message) { + const ptr0 = passArray8ToWasm0(message, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.sign(ptr0, len0); + return ret; +} + +function __wbg_adapter_32(arg0, arg1, arg2) { + wasm.closure89_externref_shim(arg0, arg1, arg2); +} + +function __wbg_adapter_35(arg0, arg1, arg2) { + wasm.closure133_externref_shim(arg0, arg1, arg2); +} + +function __wbg_adapter_38(arg0, arg1, arg2) { + wasm.closure188_externref_shim(arg0, arg1, arg2); +} + +function __wbg_adapter_135(arg0, arg1, arg2, arg3) { + wasm.closure1847_externref_shim(arg0, arg1, arg2, arg3); +} + +const __wbindgen_enum_IdbTransactionMode = ["readonly", "readwrite", "versionchange", "readwriteflush", "cleanup"]; + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) { + const ret = arg0.buffer; + return ret; + }; + imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.call(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_call_7cccdd69e0791ae2 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.call(arg1, arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_createObjectStore_d2f9e1016f4d81b9 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg0.createObjectStore(getStringFromWasm0(arg1, arg2), arg3); + return ret; + }, arguments) }; + imports.wbg.__wbg_crypto_574e78ad8b13b65f = function(arg0) { + const ret = arg0.crypto; + return ret; + }; + imports.wbg.__wbg_error_524f506f44df1645 = function(arg0) { + console.error(arg0); + }; + imports.wbg.__wbg_error_ff4ddaabdfc5dbb3 = function() { return handleError(function (arg0) { + const ret = arg0.error; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }, arguments) }; + imports.wbg.__wbg_getRandomValues_3c9c0d586e575a16 = function() { return handleError(function (arg0, arg1) { + globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1)); + }, arguments) }; + imports.wbg.__wbg_getRandomValues_b8f5dbd5f3995a9e = function() { return handleError(function (arg0, arg1) { + arg0.getRandomValues(arg1); + }, arguments) }; + imports.wbg.__wbg_getTime_46267b1c24877e30 = function(arg0) { + const ret = arg0.getTime(); + return ret; + }; + imports.wbg.__wbg_get_4f73335ab78445db = function(arg0, arg1, arg2) { + const ret = arg1[arg2 >>> 0]; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbg_get_67b2ba62fc30de12 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(arg0, arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_get_8da03f81f6a1111e = function() { return handleError(function (arg0, arg1) { + const ret = arg0.get(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_instanceof_IdbDatabase_a3ef009ca00059f9 = function(arg0) { + let result; + try { + result = arg0 instanceof IDBDatabase; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_IdbFactory_12eaba3366f4302f = function(arg0) { + let result; + try { + result = arg0 instanceof IDBFactory; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_IdbOpenDbRequest_a3416e156c9db893 = function(arg0) { + let result; + try { + result = arg0 instanceof IDBOpenDBRequest; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_IdbRequest_4813c3f207666aa4 = function(arg0) { + let result; + try { + result = arg0 instanceof IDBRequest; + } catch (_) { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_length_52b6c4580c5ec934 = function(arg0) { + const ret = arg0.length; + return ret; + }; + imports.wbg.__wbg_msCrypto_a61aeb35a24c1329 = function(arg0) { + const ret = arg0.msCrypto; + return ret; + }; + imports.wbg.__wbg_new0_f788a2397c7ca929 = function() { + const ret = new Date(); + return ret; + }; + imports.wbg.__wbg_new_23a2665fac83c611 = function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return __wbg_adapter_135(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return ret; + } finally { + state0.a = state0.b = 0; + } + }; + imports.wbg.__wbg_new_405e22f390576ce2 = function() { + const ret = new Object(); + return ret; + }; + imports.wbg.__wbg_new_78feb108b6472713 = function() { + const ret = new Array(); + return ret; + }; + imports.wbg.__wbg_new_a12002a7f91c75be = function(arg0) { + const ret = new Uint8Array(arg0); + return ret; + }; + imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return ret; + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a = function(arg0, arg1, arg2) { + const ret = new Uint8Array(arg0, arg1 >>> 0, arg2 >>> 0); + return ret; + }; + imports.wbg.__wbg_newwithlength_a381634e90c276d4 = function(arg0) { + const ret = new Uint8Array(arg0 >>> 0); + return ret; + }; + imports.wbg.__wbg_node_905d3e251edff8a2 = function(arg0) { + const ret = arg0.node; + return ret; + }; + imports.wbg.__wbg_now_d18023d54d4e5500 = function(arg0) { + const ret = arg0.now(); + return ret; + }; + imports.wbg.__wbg_objectStoreNames_9bb1ab04a7012aaf = function(arg0) { + const ret = arg0.objectStoreNames; + return ret; + }; + imports.wbg.__wbg_objectStore_21878d46d25b64b6 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.objectStore(getStringFromWasm0(arg1, arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_open_88b1390d99a7c691 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.open(getStringFromWasm0(arg1, arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_open_e0c0b2993eb596e1 = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = arg0.open(getStringFromWasm0(arg1, arg2), arg3 >>> 0); + return ret; + }, arguments) }; + imports.wbg.__wbg_process_dc0fbacc7c1c06f7 = function(arg0) { + const ret = arg0.process; + return ret; + }; + imports.wbg.__wbg_push_737cfc8c1432c2c6 = function(arg0, arg1) { + const ret = arg0.push(arg1); + return ret; + }; + imports.wbg.__wbg_put_066faa31a6a88f5b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.put(arg1, arg2); + return ret; + }, arguments) }; + imports.wbg.__wbg_put_9ef5363941008835 = function() { return handleError(function (arg0, arg1) { + const ret = arg0.put(arg1); + return ret; + }, arguments) }; + imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) { + queueMicrotask(arg0); + }; + imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) { + const ret = arg0.queueMicrotask; + return ret; + }; + imports.wbg.__wbg_randomFillSync_ac0988aba3254290 = function() { return handleError(function (arg0, arg1) { + arg0.randomFillSync(arg1); + }, arguments) }; + imports.wbg.__wbg_require_60cc747a6bc5215a = function() { return handleError(function () { + const ret = module.require; + return ret; + }, arguments) }; + imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) { + const ret = Promise.resolve(arg0); + return ret; + }; + imports.wbg.__wbg_result_f29afabdf2c05826 = function() { return handleError(function (arg0) { + const ret = arg0.result; + return ret; + }, arguments) }; + imports.wbg.__wbg_set_65595bdd868b3009 = function(arg0, arg1, arg2) { + arg0.set(arg1, arg2 >>> 0); + }; + imports.wbg.__wbg_setonerror_d7e3056cc6e56085 = function(arg0, arg1) { + arg0.onerror = arg1; + }; + imports.wbg.__wbg_setonsuccess_afa464ee777a396d = function(arg0, arg1) { + arg0.onsuccess = arg1; + }; + imports.wbg.__wbg_setonupgradeneeded_fcf7ce4f2eb0cb5f = function(arg0, arg1) { + arg0.onupgradeneeded = arg1; + }; + imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { + const ret = typeof global === 'undefined' ? null : global; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { + const ret = typeof globalThis === 'undefined' ? null : globalThis; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { + const ret = typeof self === 'undefined' ? null : self; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { + const ret = typeof window === 'undefined' ? null : window; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_subarray_aa9065fa9dc5df96 = function(arg0, arg1, arg2) { + const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0); + return ret; + }; + imports.wbg.__wbg_target_0a62d9d79a2a1ede = function(arg0) { + const ret = arg0.target; + return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); + }; + imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) { + const ret = arg0.then(arg1); + return ret; + }; + imports.wbg.__wbg_transaction_d6d07c3c9963c49e = function() { return handleError(function (arg0, arg1, arg2) { + const ret = arg0.transaction(arg1, __wbindgen_enum_IdbTransactionMode[arg2]); + return ret; + }, arguments) }; + imports.wbg.__wbg_versions_c01dfd4722a88165 = function(arg0) { + const ret = arg0.versions; + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = arg0.original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper288 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 90, __wbg_adapter_32); + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper518 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 134, __wbg_adapter_35); + return ret; + }; + imports.wbg.__wbindgen_closure_wrapper776 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 189, __wbg_adapter_38); + return ret; + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(arg1); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbindgen_init_externref_table = function() { + const table = wasm.__wbindgen_export_2; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + ; + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(arg0) === 'function'; + return ret; + }; + imports.wbg.__wbindgen_is_null = function(arg0) { + const ret = arg0 === null; + return ret; + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = arg0; + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(arg0) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = arg0 === undefined; + return ret; + }; + imports.wbg.__wbindgen_json_parse = function(arg0, arg1) { + const ret = JSON.parse(getStringFromWasm0(arg0, arg1)); + return ret; + }; + imports.wbg.__wbindgen_json_serialize = function(arg0, arg1) { + const obj = arg1; + const ret = JSON.stringify(obj === undefined ? null : obj); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return ret; + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + return imports; +} + +function __wbg_init_memory(imports, memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedDataViewMemory0 = null; + cachedUint8ArrayMemory0 = null; + + + wasm.__wbindgen_start(); + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (typeof module !== 'undefined') { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (typeof module_or_path !== 'undefined') { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + if (typeof module_or_path === 'undefined') { + module_or_path = new URL('wasm_app_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync }; +export default __wbg_init; diff --git a/wasm_console_demo/wasm_app_bg.wasm b/wasm_console_demo/wasm_app_bg.wasm new file mode 100644 index 0000000..d5b242e Binary files /dev/null and b/wasm_console_demo/wasm_app_bg.wasm differ diff --git a/wasm_console_demo/wasm_app_bg.wasm.d.ts b/wasm_console_demo/wasm_app_bg.wasm.d.ts new file mode 100644 index 0000000..b4a5c52 --- /dev/null +++ b/wasm_console_demo/wasm_app_bg.wasm.d.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export const init_rhai_env: () => void; +export const run_rhai: (a: number, b: number) => [number, number, number]; +export const create_keyspace: (a: number, b: number, c: number, d: number) => any; +export const init_session: (a: number, b: number, c: number, d: number) => any; +export const lock_session: () => void; +export const current_keypair_metadata: () => [number, number, number]; +export const current_keypair_public_key: () => [number, number, number]; +export const is_unlocked: () => number; +export const select_keypair: (a: number, b: number) => [number, number]; +export const list_keypairs: () => any; +export const add_keypair: (a: number, b: number, c: number, d: number) => any; +export const sign: (a: number, b: number) => any; +export const __wbindgen_exn_store: (a: number) => void; +export const __externref_table_alloc: () => number; +export const __wbindgen_export_2: WebAssembly.Table; +export const __wbindgen_malloc: (a: number, b: number) => number; +export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; +export const __wbindgen_export_5: WebAssembly.Table; +export const __externref_table_dealloc: (a: number) => void; +export const closure89_externref_shim: (a: number, b: number, c: any) => void; +export const closure133_externref_shim: (a: number, b: number, c: any) => void; +export const closure188_externref_shim: (a: number, b: number, c: any) => void; +export const closure1847_externref_shim: (a: number, b: number, c: any, d: any) => void; +export const __wbindgen_start: () => void;