1#![forbid(unsafe_code)]
8#![warn(missing_docs)]
9#![warn(rustdoc::bare_urls)]
10#![warn(clippy::large_futures)]
11
12use std::fmt;
13
14use nostr::prelude::*;
15use thiserror::Error;
16
17#[cfg(feature = "nip46")]
18pub mod nip46;
19pub mod prelude;
20
21#[cfg(feature = "nip46")]
22pub use self::nip46::{Nip46Signer, NostrConnectRemoteSigner, NostrConnectSignerActions};
23
24#[derive(Debug, Error)]
26pub enum Error {
27 #[error(transparent)]
29 Keys(#[from] key::Error),
30 #[error(transparent)]
32 Unsigned(#[from] unsigned::Error),
33 #[cfg(feature = "nip04")]
35 #[error(transparent)]
36 NIP04(#[from] nip04::Error),
37 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
39 #[error(transparent)]
40 NIP07(#[from] nip07::Error),
41 #[cfg(feature = "nip44")]
43 #[error(transparent)]
44 NIP44(#[from] nip44::Error),
45 #[cfg(feature = "nip46")]
47 #[error(transparent)]
48 NIP46(#[from] nip46::Error),
49 #[cfg(feature = "nip59")]
51 #[error(transparent)]
52 NIP59(#[from] nip59::Error),
53 #[cfg(feature = "nip59")]
55 #[error(transparent)]
56 Event(#[from] event::Error),
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
61pub enum NostrSignerType {
62 Keys,
64 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
66 NIP07,
67 #[cfg(feature = "nip46")]
69 NIP46,
70}
71
72impl fmt::Display for NostrSignerType {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Self::Keys => write!(f, "Keys"),
77 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
78 Self::NIP07 => write!(f, "Nostr Browser Extension"),
79 #[cfg(feature = "nip46")]
80 Self::NIP46 => write!(f, "Nostr Connect"),
81 }
82 }
83}
84
85#[derive(Debug, Clone)]
87pub enum NostrSigner {
88 Keys(Keys),
90 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
92 NIP07(Nip07Signer),
93 #[cfg(feature = "nip46")]
95 NIP46(Box<Nip46Signer>),
96}
97
98impl NostrSigner {
99 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
101 pub fn nip07() -> Result<Self, Error> {
102 let instance = Nip07Signer::new()?;
103 Ok(Self::NIP07(instance))
104 }
105
106 #[cfg(feature = "nip46")]
108 pub fn nip46(signer: Nip46Signer) -> Self {
109 Self::NIP46(Box::new(signer))
110 }
111
112 pub fn r#type(&self) -> NostrSignerType {
114 match self {
115 Self::Keys(..) => NostrSignerType::Keys,
116 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
117 Self::NIP07(..) => NostrSignerType::NIP07,
118 #[cfg(feature = "nip46")]
119 Self::NIP46(..) => NostrSignerType::NIP46,
120 }
121 }
122
123 pub async fn public_key(&self) -> Result<PublicKey, Error> {
125 match self {
126 Self::Keys(keys) => Ok(keys.public_key()),
127 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
128 Self::NIP07(s) => Ok(s.get_public_key().await?),
129 #[cfg(feature = "nip46")]
130 Self::NIP46(s) => Ok(s.signer_public_key()),
131 }
132 }
133
134 pub async fn sign_event_builder(&self, builder: EventBuilder) -> Result<Event, Error> {
136 let public_key: PublicKey = self.public_key().await?;
137 let unsigned: UnsignedEvent = builder.to_unsigned_event(public_key);
138 self.sign_event(unsigned).await
139 }
140
141 pub async fn sign_event(&self, unsigned: UnsignedEvent) -> Result<Event, Error> {
143 match self {
144 Self::Keys(keys) => Ok(unsigned.sign(keys)?),
145 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
146 Self::NIP07(nip07) => Ok(nip07.sign_event(unsigned).await?),
147 #[cfg(feature = "nip46")]
148 Self::NIP46(nip46) => Ok(nip46.sign_event(unsigned).await?),
149 }
150 }
151
152 #[cfg(feature = "nip04")]
154 pub async fn nip04_encrypt<T>(
155 &self,
156 public_key: &PublicKey,
157 content: T,
158 ) -> Result<String, Error>
159 where
160 T: AsRef<[u8]>,
161 {
162 let content: &[u8] = content.as_ref();
163 match self {
164 Self::Keys(keys) => Ok(nip04::encrypt(keys.secret_key(), public_key, content)?),
165 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
166 Self::NIP07(signer) => Ok(signer.nip04_encrypt(public_key, content).await?),
167 #[cfg(feature = "nip46")]
168 Self::NIP46(signer) => Ok(signer.nip04_encrypt(*public_key, content).await?),
169 }
170 }
171
172 #[cfg(feature = "nip04")]
174 pub async fn nip04_decrypt<T>(
175 &self,
176 public_key: &PublicKey,
177 encrypted_content: T,
178 ) -> Result<String, Error>
179 where
180 T: AsRef<str>,
181 {
182 let encrypted_content: &str = encrypted_content.as_ref();
183 match self {
184 Self::Keys(keys) => Ok(nip04::decrypt(
185 keys.secret_key(),
186 public_key,
187 encrypted_content,
188 )?),
189 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
190 Self::NIP07(signer) => Ok(signer.nip04_decrypt(public_key, encrypted_content).await?),
191 #[cfg(feature = "nip46")]
192 Self::NIP46(signer) => Ok(signer.nip04_decrypt(*public_key, encrypted_content).await?),
193 }
194 }
195
196 #[cfg(feature = "nip44")]
198 pub async fn nip44_encrypt<T>(
199 &self,
200 public_key: &PublicKey,
201 content: T,
202 ) -> Result<String, Error>
203 where
204 T: AsRef<[u8]>,
205 {
206 let content: &[u8] = content.as_ref();
207 match self {
208 Self::Keys(keys) => Ok(nip44::encrypt(
209 keys.secret_key(),
210 public_key,
211 content,
212 nip44::Version::default(),
213 )?),
214 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
215 Self::NIP07(signer) => Ok(signer.nip44_encrypt(public_key, content).await?),
216 #[cfg(feature = "nip46")]
217 Self::NIP46(signer) => Ok(signer.nip44_encrypt(*public_key, content).await?),
218 }
219 }
220
221 #[cfg(feature = "nip44")]
223 pub async fn nip44_decrypt<T>(
224 &self,
225 public_key: &PublicKey,
226 payload: T,
227 ) -> Result<String, Error>
228 where
229 T: AsRef<[u8]>,
230 {
231 let payload: &[u8] = payload.as_ref();
232 match self {
233 Self::Keys(keys) => Ok(nip44::decrypt(keys.secret_key(), public_key, payload)?),
234 #[cfg(all(feature = "nip07", target_arch = "wasm32"))]
235 Self::NIP07(signer) => Ok(signer.nip44_decrypt(public_key, payload).await?),
236 #[cfg(feature = "nip46")]
237 Self::NIP46(signer) => Ok(signer.nip44_decrypt(*public_key, payload).await?),
238 }
239 }
240
241 #[cfg(feature = "nip59")]
248 pub async fn unwrap_gift_wrap(&self, gift_wrap: &Event) -> Result<UnwrappedGift, Error> {
249 if gift_wrap.kind != Kind::GiftWrap {
251 return Err(Error::NIP59(nip59::Error::NotGiftWrap));
252 }
253
254 let seal: String = self
256 .nip44_decrypt(&gift_wrap.pubkey, &gift_wrap.content)
257 .await?;
258 let seal: Event = Event::from_json(seal)?;
259 seal.verify()?;
260
261 let rumor: String = self.nip44_decrypt(&seal.pubkey, &seal.content).await?;
263
264 Ok(UnwrappedGift {
265 sender: seal.pubkey,
266 rumor: UnsignedEvent::from_json(rumor)?,
267 })
268 }
269}
270
271impl From<Keys> for NostrSigner {
272 fn from(keys: Keys) -> Self {
273 Self::Keys(keys)
274 }
275}
276
277impl From<&Keys> for NostrSigner {
278 fn from(keys: &Keys) -> Self {
279 Self::Keys(keys.clone())
280 }
281}
282
283#[cfg(all(feature = "nip07", target_arch = "wasm32"))]
284impl From<Nip07Signer> for NostrSigner {
285 fn from(nip07: Nip07Signer) -> Self {
286 Self::NIP07(nip07)
287 }
288}
289
290#[cfg(feature = "nip46")]
291impl From<Nip46Signer> for NostrSigner {
292 fn from(nip46: Nip46Signer) -> Self {
293 Self::nip46(nip46)
294 }
295}