contextvm_sdk/relay/
mod.rs1#[cfg(any(test, feature = "test-utils"))]
6pub mod mock;
7#[cfg(any(test, feature = "test-utils"))]
8pub use mock::MockRelayPool;
9
10use async_trait::async_trait;
11
12use crate::core::error::{Error, Result};
13use nostr_sdk::prelude::*;
14use std::sync::Arc;
15
16#[async_trait]
18pub trait RelayPoolTrait: Send + Sync {
19 async fn connect(&self, relay_urls: &[String]) -> Result<()>;
21 async fn disconnect(&self) -> Result<()>;
23 async fn publish_event(&self, event: &Event) -> Result<EventId>;
25 async fn publish(&self, builder: EventBuilder) -> Result<EventId>;
27 async fn sign(&self, builder: EventBuilder) -> Result<Event>;
29 async fn signer(&self) -> Result<Arc<dyn NostrSigner>>;
31 fn notifications(&self) -> tokio::sync::broadcast::Receiver<RelayPoolNotification>;
33 async fn public_key(&self) -> Result<PublicKey>;
35 async fn subscribe(&self, filters: Vec<Filter>) -> Result<()>;
37}
38
39pub struct RelayPool {
41 client: Arc<Client>,
42}
43
44impl RelayPool {
45 pub async fn new<T>(signer: T) -> Result<Self>
47 where
48 T: IntoNostrSigner,
49 {
50 let client = Client::builder().signer(signer).build();
51
52 Ok(Self {
53 client: Arc::new(client),
54 })
55 }
56
57 pub async fn connect(&self, relay_urls: &[String]) -> Result<()> {
59 for url in relay_urls {
60 self.client
61 .add_relay(url)
62 .await
63 .map_err(|e| Error::Transport(e.to_string()))?;
64 }
65
66 self.client.connect().await;
67
68 Ok(())
69 }
70
71 pub async fn disconnect(&self) -> Result<()> {
73 self.client.disconnect().await;
74 Ok(())
75 }
76
77 pub async fn publish_event(&self, event: &Event) -> Result<EventId> {
79 let output = self
80 .client
81 .send_event(event)
82 .await
83 .map_err(|e| Error::Transport(e.to_string()))?;
84 Ok(output.val)
85 }
86
87 pub async fn publish(&self, builder: EventBuilder) -> Result<EventId> {
89 let output = self
90 .client
91 .send_event_builder(builder)
92 .await
93 .map_err(|e| Error::Transport(e.to_string()))?;
94 Ok(output.val)
95 }
96
97 pub async fn sign(&self, builder: EventBuilder) -> Result<Event> {
99 self.client
100 .sign_event_builder(builder)
101 .await
102 .map_err(|e| Error::Transport(e.to_string()))
103 }
104
105 pub fn client(&self) -> &Arc<Client> {
107 &self.client
108 }
109
110 pub fn notifications(&self) -> tokio::sync::broadcast::Receiver<RelayPoolNotification> {
112 self.client.notifications()
113 }
114
115 pub async fn public_key(&self) -> Result<PublicKey> {
117 let signer = self
118 .client
119 .signer()
120 .await
121 .map_err(|e| Error::Other(e.to_string()))?;
122 signer
123 .get_public_key()
124 .await
125 .map_err(|e| Error::Other(e.to_string()))
126 }
127
128 pub async fn subscribe(&self, filters: Vec<Filter>) -> Result<()> {
130 for filter in filters {
131 self.client
132 .subscribe(filter, None)
133 .await
134 .map_err(|e| Error::Transport(e.to_string()))?;
135 }
136 Ok(())
137 }
138}
139
140#[async_trait]
141impl RelayPoolTrait for RelayPool {
142 async fn connect(&self, relay_urls: &[String]) -> Result<()> {
143 RelayPool::connect(self, relay_urls).await
144 }
145
146 async fn disconnect(&self) -> Result<()> {
147 RelayPool::disconnect(self).await
148 }
149
150 async fn publish_event(&self, event: &Event) -> Result<EventId> {
151 RelayPool::publish_event(self, event).await
152 }
153
154 async fn publish(&self, builder: EventBuilder) -> Result<EventId> {
155 RelayPool::publish(self, builder).await
156 }
157
158 async fn sign(&self, builder: EventBuilder) -> Result<Event> {
159 RelayPool::sign(self, builder).await
160 }
161
162 async fn signer(&self) -> Result<Arc<dyn NostrSigner>> {
163 self.client
164 .signer()
165 .await
166 .map_err(|e| Error::Other(e.to_string()))
167 }
168
169 fn notifications(&self) -> tokio::sync::broadcast::Receiver<RelayPoolNotification> {
170 RelayPool::notifications(self)
171 }
172
173 async fn public_key(&self) -> Result<PublicKey> {
174 RelayPool::public_key(self).await
175 }
176
177 async fn subscribe(&self, filters: Vec<Filter>) -> Result<()> {
178 RelayPool::subscribe(self, filters).await
179 }
180}