diff --git a/packages/rs-platform-wallet-ffi/src/spv.rs b/packages/rs-platform-wallet-ffi/src/spv.rs index 55ece2d51b..47a603548b 100644 --- a/packages/rs-platform-wallet-ffi/src/spv.rs +++ b/packages/rs-platform-wallet-ffi/src/spv.rs @@ -358,10 +358,19 @@ pub unsafe extern "C" fn platform_wallet_manager_spv_start( config.devnet = Some(devnet); } - let _guard = runtime().enter(); - manager.spv_arc().spawn_in_background(config); + let start_result = runtime().block_on(manager.spv().start(config)); + + if start_result.is_ok() { + let _guard = runtime().enter(); + manager.spv_arc().spawn_run_loop(); + } + + start_result }); - unwrap_option_or_return!(option); + + let start_result = unwrap_option_or_return!(option); + unwrap_result_or_return!(start_result); + PlatformWalletFFIResult::ok() } diff --git a/packages/rs-platform-wallet/src/error.rs b/packages/rs-platform-wallet/src/error.rs index 598b1b4283..9db2dc076f 100644 --- a/packages/rs-platform-wallet/src/error.rs +++ b/packages/rs-platform-wallet/src/error.rs @@ -149,9 +149,6 @@ pub enum PlatformWalletError { #[error("No wallets configured — add a wallet before starting SPV")] NoWalletsConfigured, - #[error("SPV client is not running")] - SpvNotRunning, - #[error("SPV error: {0}")] SpvError(String), diff --git a/packages/rs-platform-wallet/src/manager/accessors.rs b/packages/rs-platform-wallet/src/manager/accessors.rs index 578079f998..168289b533 100644 --- a/packages/rs-platform-wallet/src/manager/accessors.rs +++ b/packages/rs-platform-wallet/src/manager/accessors.rs @@ -213,7 +213,7 @@ impl PlatformWalletManager

{ } /// Clone the `Arc` so callers (e.g. FFI) can invoke - /// [`SpvRuntime::spawn_in_background`] which takes `&Arc`. + /// [`SpvRuntime::spawn_run_loop`] which takes `&Arc`. pub fn spv_arc(&self) -> Arc { Arc::clone(&self.spv_manager) } diff --git a/packages/rs-platform-wallet/src/spv/runtime.rs b/packages/rs-platform-wallet/src/spv/runtime.rs index 215f3022bb..b59784b7c3 100644 --- a/packages/rs-platform-wallet/src/spv/runtime.rs +++ b/packages/rs-platform-wallet/src/spv/runtime.rs @@ -97,9 +97,9 @@ impl SpvRuntime { tx: &Transaction, ) -> Result<(), PlatformWalletError> { let client_guard = self.client.read().await; - let client = client_guard - .as_ref() - .ok_or(PlatformWalletError::SpvNotRunning)?; + let client = client_guard.as_ref().ok_or(PlatformWalletError::SpvError( + "SPV Client not started".to_string(), + ))?; client .broadcast_transaction(tx) @@ -117,9 +117,9 @@ impl SpvRuntime { height: u32, ) -> Result<[u8; 48], PlatformWalletError> { let client_guard = self.client.read().await; - let client = client_guard - .as_ref() - .ok_or(PlatformWalletError::SpvNotRunning)?; + let client = client_guard.as_ref().ok_or(PlatformWalletError::SpvError( + "SPV Client not started".to_string(), + ))?; let llmq_type = LLMQType::from(quorum_type as u8); let qh = QuorumHash::from_byte_array(quorum_hash).reverse(); @@ -132,16 +132,16 @@ impl SpvRuntime { Ok(*quorum.quorum_entry.quorum_public_key.as_ref()) } - /// Run the SPV sync loop until calling [`stop`]. This blocks the current thread. - pub async fn run(&self, config: ClientConfig) -> Result<(), PlatformWalletError> { - tracing::info!("SpvRuntime::run() starting client..."); - self.start(config).await?; - tracing::info!("SpvRuntime::run() client started, entering sync loop"); - + /// Drive the sync loop of an already-[`start`]ed client until [`stop`] + /// is called. + /// [`spawn_run_loop`](Self::spawn_run_loop). + async fn run(&self) -> Result<(), PlatformWalletError> { let client_guard = self.client.read().await; let client = client_guard .as_ref() - .ok_or(PlatformWalletError::SpvNotRunning)? + .ok_or(PlatformWalletError::SpvError( + "SPV Client not started".to_string(), + ))? .clone(); drop(client_guard); @@ -189,10 +189,11 @@ impl SpvRuntime { stop_result } - /// Spawn `run()` on the current tokio runtime and return immediately. + /// Spawn the sync loop of an already-[`start`]ed client on the current + /// tokio runtime and return immediately. /// /// Call [`stop`] to stop it - pub fn spawn_in_background(self: &Arc, config: ClientConfig) { + pub fn spawn_run_loop(self: &Arc) { { let existing = self.task.lock().expect("spv task mutex poisoned"); if existing.is_some() { @@ -206,8 +207,8 @@ impl SpvRuntime { let this = Arc::clone(self); let handle = tokio::spawn(async move { - if let Err(e) = this.run(config).await { - tracing::warn!("SpvRuntime background run exited with error: {}", e); + if let Err(e) = this.run().await { + tracing::warn!("SpvRuntime background run loop exited with error: {}", e); } }); @@ -252,9 +253,10 @@ impl SpvRuntime { /// The SPV client must be running to perform this operation. pub async fn clear_storage(&self) -> Result<(), PlatformWalletError> { let client_guard = self.client.read().await; - let client = client_guard - .as_ref() - .ok_or(PlatformWalletError::SpvNotRunning)?; + let client = client_guard.as_ref().ok_or(PlatformWalletError::SpvError( + "SPV Client not started".to_string(), + ))?; + client .clear_storage() .await @@ -266,9 +268,10 @@ impl SpvRuntime { /// The network cannot be changed on a running client. pub async fn update_config(&self, config: ClientConfig) -> Result<(), PlatformWalletError> { let client_guard = self.client.read().await; - let client = client_guard - .as_ref() - .ok_or(PlatformWalletError::SpvNotRunning)?; + let client = client_guard.as_ref().ok_or(PlatformWalletError::SpvError( + "SPV Client not started".to_string(), + ))?; + client .update_config(config) .await