use alloc::borrow::Cow;
use alloc::string::{String, ToString};
use core::any::Any;
use core::fmt::{self, Debug, Display};
use crate::nips::nip04::{AsyncNip04, Nip04};
use crate::nips::nip44::{AsyncNip44, Nip44};
use crate::util::BoxedFuture;
use crate::{Event, PublicKey, UnsignedEvent};
#[derive(Debug, PartialEq, Eq)]
pub struct SignerError(String);
impl core::error::Error for SignerError {}
impl fmt::Display for SignerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.0.as_str())
}
}
impl SignerError {
#[inline]
pub fn backend<E>(error: E) -> Self
where
E: Display,
{
Self(error.to_string())
}
}
impl<S> From<S> for SignerError
where
S: Into<String>,
{
fn from(error: S) -> Self {
Self(error.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SignerBackend<'a> {
Keys,
BrowserExtension,
NostrConnect,
Custom(Cow<'a, str>),
}
pub trait AsyncNostrSigner:
AsyncGetPublicKey
+ AsyncSignEvent
+ AsyncNip04<Error = SignerError>
+ AsyncNip44<Error = SignerError>
{
fn backend(&self) -> SignerBackend<'_>;
}
pub trait AsyncGetPublicKey: Any + Debug + Send + Sync {
fn get_public_key_async(&self) -> BoxedFuture<'_, Result<PublicKey, SignerError>>;
}
pub trait AsyncSignEvent: Any + Debug + Send + Sync {
fn sign_event_async(
&self,
unsigned: UnsignedEvent,
) -> BoxedFuture<'_, Result<Event, SignerError>>;
}
impl<T> AsyncGetPublicKey for T
where
T: AsRef<dyn AsyncNostrSigner> + Debug + Send + Sync + 'static,
{
#[inline]
fn get_public_key_async(&self) -> BoxedFuture<'_, Result<PublicKey, SignerError>> {
self.as_ref().get_public_key_async()
}
}
impl<T> AsyncSignEvent for T
where
T: AsRef<dyn AsyncNostrSigner> + Debug + Send + Sync + 'static,
{
#[inline]
fn sign_event_async(
&self,
unsigned: UnsignedEvent,
) -> BoxedFuture<'_, Result<Event, SignerError>> {
self.as_ref().sign_event_async(unsigned)
}
}
impl<T> AsyncNip04 for T
where
T: AsRef<dyn AsyncNostrSigner> + Debug + Send + Sync + 'static,
{
type Error = SignerError;
#[inline]
fn nip04_encrypt_async<'a>(
&'a self,
public_key: &'a PublicKey,
content: &'a str,
) -> BoxedFuture<'a, Result<String, Self::Error>> {
self.as_ref().nip04_encrypt_async(public_key, content)
}
#[inline]
fn nip04_decrypt_async<'a>(
&'a self,
public_key: &'a PublicKey,
encrypted_content: &'a str,
) -> BoxedFuture<'a, Result<String, Self::Error>> {
self.as_ref()
.nip04_decrypt_async(public_key, encrypted_content)
}
}
impl<T> AsyncNip44 for T
where
T: AsRef<dyn AsyncNostrSigner> + Debug + Send + Sync + 'static,
{
type Error = SignerError;
#[inline]
fn nip44_encrypt_async<'a>(
&'a self,
public_key: &'a PublicKey,
content: &'a str,
) -> BoxedFuture<'a, Result<String, Self::Error>> {
self.as_ref().nip44_encrypt_async(public_key, content)
}
#[inline]
fn nip44_decrypt_async<'a>(
&'a self,
public_key: &'a PublicKey,
payload: &'a str,
) -> BoxedFuture<'a, Result<String, Self::Error>> {
self.as_ref().nip44_decrypt_async(public_key, payload)
}
}
pub trait GetPublicKey: Any + Debug + Send + Sync {
fn get_public_key(&self) -> Result<PublicKey, SignerError>;
}
pub trait SignEvent: Any + Debug + Send + Sync {
fn sign_event(&self, unsigned: UnsignedEvent) -> Result<Event, SignerError>;
}
pub trait NostrSigner:
GetPublicKey + SignEvent + Nip04<Error = SignerError> + Nip44<Error = SignerError>
{
fn backend(&self) -> SignerBackend<'_>;
}
impl<T> GetPublicKey for T
where
T: AsRef<dyn NostrSigner> + Debug + Send + Sync + 'static,
{
#[inline]
fn get_public_key(&self) -> Result<PublicKey, SignerError> {
self.as_ref().get_public_key()
}
}
impl<T> SignEvent for T
where
T: AsRef<dyn NostrSigner> + Debug + Send + Sync + 'static,
{
#[inline]
fn sign_event(&self, unsigned: UnsignedEvent) -> Result<Event, SignerError> {
self.as_ref().sign_event(unsigned)
}
}
impl<T> Nip04 for T
where
T: AsRef<dyn NostrSigner> + Debug + Send + Sync + 'static,
{
type Error = SignerError;
#[inline]
fn nip04_encrypt(&self, public_key: &PublicKey, content: &str) -> Result<String, SignerError> {
self.as_ref().nip04_encrypt(public_key, content)
}
#[inline]
fn nip04_decrypt(
&self,
public_key: &PublicKey,
encrypted_content: &str,
) -> Result<String, SignerError> {
self.as_ref().nip04_decrypt(public_key, encrypted_content)
}
}
impl<T> Nip44 for T
where
T: AsRef<dyn NostrSigner> + Debug + Send + Sync + 'static,
{
type Error = SignerError;
#[inline]
fn nip44_encrypt(&self, public_key: &PublicKey, content: &str) -> Result<String, Self::Error> {
self.as_ref().nip44_encrypt(public_key, content)
}
#[inline]
fn nip44_decrypt(&self, public_key: &PublicKey, payload: &str) -> Result<String, Self::Error> {
self.as_ref().nip44_decrypt(public_key, payload)
}
}