openzeppelin_relayer/services/signer/
mod.rs1#![allow(unused_imports)]
25use async_trait::async_trait;
26use eyre::Result;
27#[cfg(test)]
28use mockall::automock;
29use serde::Serialize;
30use thiserror::Error;
31
32mod evm;
33pub use evm::*;
34
35mod solana;
36pub use solana::*;
37
38mod stellar;
39pub use stellar::*;
40
41use crate::{
42 domain::{SignDataRequest, SignDataResponse, SignTransactionResponse, SignTypedDataRequest},
43 models::{
44 Address, NetworkTransactionData, NetworkType, SignerError, SignerFactoryError,
45 SignerRepoModel, SignerType, TransactionError, TransactionRepoModel,
46 },
47};
48
49#[async_trait]
50#[cfg_attr(test, automock)]
51pub trait Signer: Send + Sync {
52 async fn address(&self) -> Result<Address, SignerError>;
54
55 async fn sign_transaction(
57 &self,
58 transaction: NetworkTransactionData,
59 ) -> Result<SignTransactionResponse, SignerError>;
60}
61
62#[allow(dead_code)]
63#[allow(clippy::large_enum_variant)]
64pub enum NetworkSigner {
65 Evm(EvmSigner),
66 Solana(SolanaSigner),
67 Stellar(StellarSigner),
68}
69
70#[async_trait]
71impl Signer for NetworkSigner {
72 async fn address(&self) -> Result<Address, SignerError> {
73 match self {
74 Self::Evm(signer) => signer.address().await,
75 Self::Solana(signer) => signer.address().await,
76 Self::Stellar(signer) => signer.address().await,
77 }
78 }
79
80 async fn sign_transaction(
81 &self,
82 transaction: NetworkTransactionData,
83 ) -> Result<SignTransactionResponse, SignerError> {
84 match self {
85 Self::Evm(signer) => signer.sign_transaction(transaction).await,
86 Self::Solana(signer) => signer.sign_transaction(transaction).await,
87 Self::Stellar(signer) => signer.sign_transaction(transaction).await,
88 }
89 }
90}
91
92#[async_trait]
93impl DataSignerTrait for NetworkSigner {
94 async fn sign_data(&self, request: SignDataRequest) -> Result<SignDataResponse, SignerError> {
95 match self {
96 Self::Evm(signer) => {
97 let signature = signer
98 .sign_data(request)
99 .await
100 .map_err(|e| SignerError::SigningError(e.to_string()))?;
101
102 Ok(signature)
103 }
104 Self::Solana(_) => Err(SignerError::UnsupportedTypeError(
105 "Solana: sign data not supported".into(),
106 )),
107 Self::Stellar(_) => Err(SignerError::UnsupportedTypeError(
108 "Stellar: sign data not supported".into(),
109 )),
110 }
111 }
112
113 async fn sign_typed_data(
114 &self,
115 request: SignTypedDataRequest,
116 ) -> Result<SignDataResponse, SignerError> {
117 match self {
118 Self::Evm(signer) => signer
119 .sign_typed_data(request)
120 .await
121 .map_err(|e| SignerError::SigningError(e.to_string())),
122 Self::Solana(_) => Err(SignerError::UnsupportedTypeError(
123 "Solana: Signing typed data not supported".into(),
124 )),
125 Self::Stellar(_) => Err(SignerError::UnsupportedTypeError(
126 "Stellar: Signing typed data not supported".into(),
127 )),
128 }
129 }
130}
131
132pub struct SignerFactory;
133
134impl SignerFactory {
135 pub async fn create_signer(
136 network_type: &NetworkType,
137 signer_model: &SignerRepoModel,
138 ) -> Result<NetworkSigner, SignerFactoryError> {
139 let signer = match network_type {
140 NetworkType::Evm => {
141 let evm_signer = EvmSignerFactory::create_evm_signer(signer_model.clone()).await?;
142 NetworkSigner::Evm(evm_signer)
143 }
144 NetworkType::Solana => {
145 let solana_signer = SolanaSignerFactory::create_solana_signer(signer_model)?;
146 NetworkSigner::Solana(solana_signer)
147 }
148 NetworkType::Stellar => {
149 let stellar_signer = StellarSignerFactory::create_stellar_signer(signer_model)?;
150 NetworkSigner::Stellar(stellar_signer)
151 }
152 };
153
154 Ok(signer)
155 }
156}