diff --git a/Cargo.toml b/Cargo.toml index e624a81..cc03ebd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib", "rlib"] default = [] parallel = ["sp-client/parallel"] blindbit-backend = ["backend-blindbit-native"] -blindbit-wasm = ["backend-blindbit-wasm", "dep:js-sys", "dep:serde-wasm-bindgen"] +blindbit-wasm = ["backend-blindbit-wasm", "dep:js-sys", "dep:serde-wasm-bindgen", "dep:futures"] [dependencies] aes-gcm = "0.10.3" @@ -32,4 +32,5 @@ wasm-bindgen = "0.2.91" # WASM-specific dependencies (optional) js-sys = { version = "0.3.69", optional = true } serde-wasm-bindgen = { version = "0.6.5", optional = true } +futures = { version = "0.3", optional = true } diff --git a/src/updates.rs b/src/updates.rs index 51ab715..c77d250 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -1,15 +1,6 @@ use anyhow::Result; use serde::{Deserialize, Serialize}; -use std::{ - mem, - sync::{ - mpsc::{self, Receiver, Sender}, - Arc, RwLock, - }, -}; -// use wasm_bindgen::prelude::*; -// use sp_client::bitcoin::absolute::Height; -// use sp_client::bitcoin::BlockHash; +use std::mem; use sp_client::{ bitcoin::{absolute::Height, BlockHash, OutPoint}, OwnedOutput, Updater, @@ -36,28 +27,28 @@ pub enum StateUpdate { }, } -// #[cfg(target_arch = "wasm32")] -// #[wasm_bindgen] -// extern "C" { -// #[wasm_bindgen(js_namespace = window)] -// fn sendScanProgress(progress: JsValue); - -// #[wasm_bindgen(js_namespace = window)] -// fn sendStateUpdate(update: JsValue); -// } +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] +use std::sync::{mpsc::{self, Receiver, Sender}}; +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] pub trait UpdateSink: Send + Sync { fn send_scan_progress(&self, progress: ScanProgress) -> Result<()>; fn send_state_update(&self, update: StateUpdate) -> Result<()>; } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +pub trait UpdateSink { + fn send_scan_progress(&self, progress: ScanProgress) -> Result<()>; + fn send_state_update(&self, update: StateUpdate) -> Result<()>; +} + +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] pub struct NativeUpdateSink { scan_tx: Sender, state_tx: Sender, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] impl NativeUpdateSink { pub fn new() -> (Self, Receiver, Receiver) { let (scan_tx, scan_rx) = mpsc::channel(); @@ -67,7 +58,7 @@ impl NativeUpdateSink { } } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] impl UpdateSink for NativeUpdateSink { fn send_scan_progress(&self, progress: ScanProgress) -> Result<()> { self.scan_tx.send(progress)?; @@ -80,36 +71,80 @@ impl UpdateSink for NativeUpdateSink { } } -// #[cfg(target_arch = "wasm32")] -// pub struct WasmUpdateSink; +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +use futures::channel::mpsc::{unbounded, UnboundedSender, UnboundedReceiver}; -// #[cfg(target_arch = "wasm32")] -// impl UpdateSink for WasmUpdateSink { -// fn send_scan_progress(&self, progress: ScanProgress) -> Result<()> { -// let js_value = serde_wasm_bindgen::to_value(&progress)?; -// sendScanProgress(js_value); -// Ok(()) -// } +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +pub struct WasmUpdateSink { + scan_tx: UnboundedSender, + state_tx: UnboundedSender, +} -// fn send_state_update(&self, update: StateUpdate) -> Result<()> { -// let js_value = serde_wasm_bindgen::to_value(&update)?; -// sendStateUpdate(js_value); -// Ok(()) -// } -// } +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +impl WasmUpdateSink { + pub fn new() -> (Rc, UnboundedReceiver, UnboundedReceiver) { + let (scan_tx, scan_rx) = unbounded(); + let (state_tx, state_rx) = unbounded(); + (Rc::new(Self { scan_tx, state_tx }), scan_rx, state_rx) + } +} + +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +impl UpdateSink for WasmUpdateSink { + fn send_scan_progress(&self, progress: ScanProgress) -> Result<()> { + self.scan_tx.unbounded_send(progress) + .map_err(|e| anyhow::Error::msg(format!("Failed to send scan progress: {}", e)))?; + Ok(()) + } + + fn send_state_update(&self, update: StateUpdate) -> Result<()> { + self.state_tx.unbounded_send(update) + .map_err(|e| anyhow::Error::msg(format!("Failed to send state update: {}", e)))?; + Ok(()) + } +} + + +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] +use std::sync::{Arc, RwLock}; + +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] // Global sink instance static UPDATE_SINK: RwLock>> = RwLock::new(None); +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +use std::cell::RefCell; +use std::rc::Rc; + +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +thread_local! { + static UPDATE_SINK: RefCell>> = RefCell::new(None); +} + +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] pub fn init_update_sink(sink: Arc) { let mut sink_guard = UPDATE_SINK.write().unwrap(); *sink_guard = Some(sink); } +#[cfg(all(not(target_arch = "wasm32"), not(feature = "blindbit-wasm")))] pub fn get_update_sink() -> Option> { UPDATE_SINK.read().unwrap().clone() } +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +pub fn init_update_sink(sink: Rc) { + UPDATE_SINK.with(|cell| { + *cell.borrow_mut() = Some(sink); + }); +} + +#[cfg(all(target_arch = "wasm32", feature = "blindbit-wasm"))] +pub fn get_update_sink() -> Option> { + UPDATE_SINK.with(|cell| cell.borrow().clone()) +} + #[derive(Debug)] pub struct StateUpdater { update: bool,