#![warn(missing_docs)]
#![warn(rustdoc::missing_doc_code_examples)]
#[cfg(feature = "http-client")]
pub mod http;
#[cfg(feature = "websocket-client")]
pub mod websocket;
#[cfg(feature = "wasm-websocket-client")]
pub mod wasm_websocket;
use std::{fmt::Debug, sync::Arc};
use async_trait::async_trait;
use futures::{lock::Mutex, stream::BoxStream};
use serde::{de::Deserialize, ser::Serialize};
use nimiq_jsonrpc_core::{Sensitive, SubscriptionId};
#[async_trait]
pub trait Client {
type Error: Debug;
async fn send_request<P, R>(&mut self, method: &str, params: &P) -> Result<R, Self::Error>
where
P: Serialize + Debug + Send + Sync,
R: for<'de> Deserialize<'de> + Debug + Send + Sync;
async fn connect_stream<T: Unpin + 'static>(
&mut self,
id: SubscriptionId,
) -> BoxStream<'static, T>
where
T: for<'de> Deserialize<'de> + Debug + Send + Sync;
async fn disconnect_stream(&mut self, id: SubscriptionId) -> Result<(), Self::Error>;
async fn close(&mut self);
}
pub struct ArcClient<C> {
inner: Arc<Mutex<C>>,
}
#[async_trait]
impl<C: Client + Send> Client for ArcClient<C> {
type Error = <C as Client>::Error;
async fn send_request<P, R>(&mut self, method: &str, params: &P) -> Result<R, Self::Error>
where
P: Serialize + Debug + Send + Sync,
R: for<'de> Deserialize<'de> + Debug + Send + Sync,
{
self.inner.lock().await.send_request(method, params).await
}
async fn connect_stream<T: Unpin + 'static>(
&mut self,
id: SubscriptionId,
) -> BoxStream<'static, T>
where
T: for<'de> Deserialize<'de> + Debug + Send + Sync,
{
self.inner.lock().await.connect_stream(id).await
}
async fn disconnect_stream(&mut self, id: SubscriptionId) -> Result<(), Self::Error> {
self.inner.lock().await.disconnect_stream(id).await
}
async fn close(&mut self) {
self.inner.lock().await.close().await
}
}
impl<C: Client> ArcClient<C> {
pub fn new(inner: C) -> Self {
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
}
impl<C> Clone for ArcClient<C> {
fn clone(&self) -> Self {
ArcClient {
inner: Arc::clone(&self.inner),
}
}
}
#[derive(Clone, Debug)]
pub struct Credentials {
pub username: String,
pub password: Sensitive<String>,
}
impl Credentials {
pub fn new<T: Into<String>, U: Into<String>>(username: T, password: U) -> Credentials {
Credentials {
username: username.into(),
password: Sensitive(password.into()),
}
}
}