fedimint_client_wasm/
lib.rs

1#![cfg(target_family = "wasm")]
2
3use std::sync::Arc;
4
5use fedimint_client_rpc::{RpcGlobalState, RpcRequest, RpcResponse, RpcResponseHandler};
6use fedimint_core::db::Database;
7use fedimint_cursed_redb::MemAndRedb;
8use wasm_bindgen::prelude::{JsError, JsValue, wasm_bindgen};
9use web_sys::FileSystemSyncAccessHandle;
10
11struct JsFunctionWrapper(js_sys::Function);
12
13impl RpcResponseHandler for JsFunctionWrapper {
14    fn handle_response(&self, response: RpcResponse) {
15        let _ = self.0.call1(
16            &JsValue::null(),
17            &JsValue::from_str(&serde_json::to_string(&response).unwrap()),
18        );
19    }
20}
21
22#[wasm_bindgen]
23struct RpcHandler {
24    state: Arc<RpcGlobalState>,
25}
26
27#[wasm_bindgen]
28impl RpcHandler {
29    #[wasm_bindgen(constructor)]
30    pub fn new(sync_handle: FileSystemSyncAccessHandle) -> Self {
31        // Create the database directly
32        let cursed_db = MemAndRedb::new(sync_handle).unwrap();
33        let database = Database::new(cursed_db, Default::default());
34
35        let state = Arc::new(RpcGlobalState::new(database));
36
37        Self { state }
38    }
39
40    #[wasm_bindgen]
41    pub fn rpc(&self, request: String, cb: js_sys::Function) -> Result<(), JsError> {
42        let request: RpcRequest = serde_json::from_str(&request)
43            .map_err(|e| JsError::new(&format!("Failed to parse request: {}", e)))?;
44
45        let handled = self
46            .state
47            .clone()
48            .handle_rpc(request, JsFunctionWrapper(cb));
49
50        if let Some(task) = handled.task {
51            wasm_bindgen_futures::spawn_local(task);
52        }
53        Ok(())
54    }
55}