cashweb_relay_client/
lib.rs1#![warn(
2 missing_debug_implementations,
3 missing_docs,
4 rust_2018_idioms,
5 unreachable_pub
6)]
7
8pub mod services;
12
13use std::{error, fmt};
14
15pub use hyper::{
16 client::{connect::Connect, HttpConnector},
17 Uri,
18};
19
20use hyper::client::Client as HyperClient;
21use hyper::http::uri::InvalidUri;
22use secp256k1::key::PublicKey;
23use thiserror::Error;
24use tower_service::Service;
25use tower_util::ServiceExt;
26
27use relay::Profile;
28use services::*;
29
30#[derive(Clone, Debug)]
32pub struct RelayClient<S> {
33 inner_client: S,
34}
35
36impl<S> RelayClient<S> {
37 pub fn from_service(service: S) -> Self {
39 Self {
40 inner_client: service,
41 }
42 }
43}
44
45impl Default for RelayClient<HyperClient<HttpConnector>> {
46 fn default() -> Self {
47 Self {
48 inner_client: HyperClient::new(),
49 }
50 }
51}
52
53impl RelayClient<HyperClient<HttpConnector>> {
54 pub fn new() -> Self {
56 Default::default()
57 }
58}
59
60#[derive(Debug, Error)]
62pub enum RelayError<E: fmt::Debug + fmt::Display + error::Error + 'static> {
63 #[error(transparent)]
65 Uri(InvalidUri),
66 #[error("failed to execute service method: {0}")]
68 Error(#[from] E),
69}
70
71#[derive(Clone, Debug)]
73pub struct ProfilePackage {
74 pub public_key: PublicKey,
76 pub profile: Profile,
78}
79
80impl<S> RelayClient<S>
81where
82 Self: Service<(Uri, GetProfile), Response = ProfilePackage>,
83 Self: Sync + Clone + Send + 'static,
84 <Self as Service<(Uri, GetProfile)>>::Future: Send + Sync + 'static,
85 <Self as Service<(Uri, GetProfile)>>::Error: fmt::Debug + fmt::Display + error::Error,
86{
87 pub async fn get_profile(
89 &self,
90 keyserver_url: &str,
91 address: &str,
92 ) -> Result<ProfilePackage, RelayError<<Self as Service<(Uri, GetProfile)>>::Error>> {
93 let full_path = format!("{}/profiles/{}", keyserver_url, address);
95 let uri: Uri = full_path.parse().map_err(RelayError::Uri)?;
96
97 let request = (uri, GetProfile);
99
100 self.clone()
101 .oneshot(request)
102 .await
103 .map_err(RelayError::Error)
104 }
105}
106
107impl<S> RelayClient<S>
108where
109 Self: Service<(Uri, PutProfile), Response = ()>,
110 Self: Sync + Clone + Send + 'static,
111 <Self as Service<(Uri, PutProfile)>>::Future: Send + Sync + 'static,
112 <Self as Service<(Uri, PutProfile)>>::Error: fmt::Debug + fmt::Display + error::Error,
113{
114 pub async fn put_profile(
116 &self,
117 relay_url: &str,
118 address: &str,
119 profile: Profile,
120 token: String,
121 ) -> Result<(), RelayError<<Self as Service<(Uri, PutProfile)>>::Error>> {
122 let full_path = format!("{}/profiles/{}", relay_url, address);
124 let uri: Uri = full_path.parse().map_err(RelayError::Uri)?;
125
126 let request = (uri, PutProfile { token, profile });
128
129 self.clone()
131 .oneshot(request)
132 .await
133 .map_err(RelayError::Error)
134 }
135}