fedimint_client_wasm/
lib.rs1#![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
11#[wasm_bindgen(start)]
22fn install_panic_hook() {
23 console_error_panic_hook::set_once();
24}
25
26struct JsFunctionWrapper(js_sys::Function);
27
28impl RpcResponseHandler for JsFunctionWrapper {
29 fn handle_response(&self, response: RpcResponse) {
30 let response = serde_json::to_string(&response).expect(
31 "RpcResponse is numbers, strings and serde_json::Value; serialization cannot fail",
32 );
33 if let Err(err) = self
34 .0
35 .call1(&JsValue::null(), &JsValue::from_str(&response))
36 {
37 web_sys::console::error_2(&JsValue::from_str("RPC response callback threw"), &err);
41 }
42 }
43}
44
45#[wasm_bindgen]
46struct RpcHandler {
47 state: Arc<RpcGlobalState>,
48}
49
50#[wasm_bindgen]
51impl RpcHandler {
52 #[wasm_bindgen(constructor)]
53 pub async fn new(sync_handle: FileSystemSyncAccessHandle) -> Result<RpcHandler, JsError> {
54 let cursed_db = MemAndRedb::new(sync_handle)
58 .map_err(|err| JsError::new(&format!("Failed to open client database: {err:#}")))?;
59 let database = Database::new(cursed_db, Default::default());
60 let connectors = fedimint_connectors::ConnectorRegistry::build_from_client_defaults()
61 .bind()
62 .await
63 .map_err(|err| JsError::new(&format!("Failed to bind client connectors: {err:#}")))?;
64
65 let state = Arc::new(RpcGlobalState::new(connectors, database));
66
67 Ok(Self { state })
68 }
69
70 #[wasm_bindgen]
71 pub fn rpc(&self, request: String, cb: js_sys::Function) -> Result<(), JsError> {
72 let request: RpcRequest = serde_json::from_str(&request)
73 .map_err(|e| JsError::new(&format!("Failed to parse request: {}", e)))?;
74
75 let handled = self
76 .state
77 .clone()
78 .handle_rpc(request, JsFunctionWrapper(cb));
79
80 if let Some(task) = handled.task {
81 wasm_bindgen_futures::spawn_local(task);
82 }
83 Ok(())
84 }
85}