use crate::SignerContext;
use std::future::Future;
use tokio::task::JoinHandle;
pub async fn spawn_with_context<F, T>(future: F) -> JoinHandle<Result<T, crate::SignerError>>
where
F: Future<Output = Result<T, crate::SignerError>> + Send + 'static,
T: Send + 'static,
{
if let Ok(signer) = SignerContext::current().await {
tokio::task::spawn(async move { SignerContext::with_signer(signer, future).await })
} else {
tokio::task::spawn(future)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_spawn_with_context_without_signer() {
let handle = spawn_with_context(async move {
match SignerContext::current().await {
Ok(_) => Err(crate::SignerError::NoSignerContext),
Err(_) => Ok(true),
}
})
.await;
let result = handle.await.unwrap().unwrap();
assert!(result, "No SignerContext should be available when not set");
}
#[tokio::test]
async fn test_spawn_with_context_with_signer() {
use crate::signer::granular_traits::{SignerBase, UnifiedSigner};
use std::{any::Any, sync::Arc};
#[derive(Debug)]
struct MockSigner;
impl SignerBase for MockSigner {
fn as_any(&self) -> &dyn Any {
self
}
}
impl UnifiedSigner for MockSigner {
fn supports_solana(&self) -> bool {
false
}
fn supports_evm(&self) -> bool {
false
}
fn as_solana(&self) -> Option<&dyn crate::signer::granular_traits::SolanaSigner> {
None
}
fn as_evm(&self) -> Option<&dyn crate::signer::granular_traits::EvmSigner> {
None
}
fn as_multi_chain(
&self,
) -> Option<&dyn crate::signer::granular_traits::MultiChainSigner> {
None
}
}
let mock_signer: Arc<dyn UnifiedSigner> = Arc::new(MockSigner);
let signer_id = format!("{:?}", mock_signer);
let result = SignerContext::with_signer(mock_signer.clone(), async move {
let handle = spawn_with_context(async move {
let current_signer = SignerContext::current().await?;
let current_id = format!("{:?}", current_signer);
if current_id == signer_id {
Ok(true)
} else {
Ok(false)
}
})
.await;
handle.await.unwrap()
})
.await;
assert!(
result.is_ok(),
"Should successfully get result from spawned task"
);
assert!(
result.unwrap(),
"SignerContext should be propagated to spawned task"
);
}
}