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 async 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        let connectors = fedimint_connectors::ConnectorRegistry::build_from_client_defaults()
35            .bind()
36            .await
37            .unwrap();
38
39        let state = Arc::new(RpcGlobalState::new(connectors, database));
40
41        Self { state }
42    }
43
44    #[wasm_bindgen]
45    pub fn rpc(&self, request: String, cb: js_sys::Function) -> Result<(), JsError> {
46        let request: RpcRequest = serde_json::from_str(&request)
47            .map_err(|e| JsError::new(&format!("Failed to parse request: {}", e)))?;
48
49        let handled = self
50            .state
51            .clone()
52            .handle_rpc(request, JsFunctionWrapper(cb));
53
54        if let Some(task) = handled.task {
55            wasm_bindgen_futures::spawn_local(task);
56        }
57        Ok(())
58    }
59}