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