builder_relayer_client_rust/
signer.rs1use ethers::signers::{LocalWallet, Signer};
2use ethers::types::{Signature, H256};
3use sha3::{Digest, Keccak256};
4
5use crate as builder_relayer_client_rust;
6use crate::errors::{RelayClientError, Result};
7
8pub trait AbstractSigner {
10 fn address(&self) -> ethers::types::Address;
11 fn sign_hash(&self, hash: H256) -> std::result::Result<Signature, RelayClientError>;
12 fn sign_eip712_digest(&self, digest: H256) -> std::result::Result<Signature, RelayClientError>;
13}
14
15pub trait TypedDataSigner {
17 fn sign_typed_create_proxy(
18 &self,
19 safe_factory: &str,
20 chain_id: u64,
21 payment_token: &str,
22 payment: &str,
23 payment_receiver: &str,
24 ) -> std::result::Result<String, RelayClientError>;
25}
26
27#[derive(Clone)]
29pub struct DummySigner {
30 wallet: LocalWallet,
31}
32
33impl DummySigner {
34 pub fn new(priv_key_hex: &str) -> std::result::Result<Self, RelayClientError> {
35 let prefixed = if priv_key_hex.starts_with("0x") {
36 priv_key_hex.to_string()
37 } else {
38 format!("0x{}", priv_key_hex)
39 };
40 let wallet: LocalWallet = prefixed
41 .parse()
42 .map_err(|_| RelayClientError::SignerUnavailable)?;
43 Ok(Self { wallet })
44 }
45}
46
47impl AbstractSigner for DummySigner {
48 fn address(&self) -> ethers::types::Address {
49 self.wallet.address()
50 }
51 fn sign_hash(&self, hash: H256) -> std::result::Result<Signature, RelayClientError> {
52 let sig = self
53 .wallet
54 .sign_hash(hash)
55 .map_err(|_| RelayClientError::SignerUnavailable)?;
56 Ok(sig)
57 }
58 fn sign_eip712_digest(&self, digest: H256) -> std::result::Result<Signature, RelayClientError> {
59 use ethers::core::k256::ecdsa::SigningKey;
63
64 let key_bytes = &self.wallet.signer().to_bytes();
65 let signing_key =
66 SigningKey::from_slice(key_bytes).map_err(|_| RelayClientError::SignerUnavailable)?;
67 let (sig, recovery_id) = signing_key
68 .sign_prehash_recoverable(digest.as_bytes())
69 .map_err(|_| RelayClientError::SignerUnavailable)?;
70
71 let r_bytes = sig.r().to_bytes();
72 let s_bytes = sig.s().to_bytes();
73 Ok(Signature {
74 r: ethers::types::U256::from_big_endian(r_bytes.as_ref()),
75 s: ethers::types::U256::from_big_endian(s_bytes.as_ref()),
76 v: recovery_id.to_byte() as u64,
77 })
78 }
79}
80
81impl TypedDataSigner for DummySigner {
82 fn sign_typed_create_proxy(
83 &self,
84 _safe_factory: &str,
85 _chain_id: u64,
86 _payment_token: &str,
87 _payment: &str,
88 _payment_receiver: &str,
89 ) -> std::result::Result<String, RelayClientError> {
90 let zero = H256::zero();
92 let sig = self.sign_hash(zero)?;
93 Ok(sig_to_hex(sig))
94 }
95}
96
97impl builder_relayer_client_rust::builder::safe::AbstractSigner for DummySigner {
99 fn get_address(&self) -> Result<String> {
100 Ok(format!("0x{:x}", self.address()))
101 }
102 fn sign_message(&self, hash32_hex: &str) -> Result<String> {
103 let bytes = hex::decode(hash32_hex.trim_start_matches("0x"))
105 .map_err(|_| RelayClientError::SignerUnavailable)?;
106 let mut arr = [0u8; 32];
107 arr.copy_from_slice(&bytes);
108 let mut msg = b"\x19Ethereum Signed Message:\n32".to_vec();
110 msg.extend_from_slice(&arr);
111 let mut hasher = Keccak256::new();
112 hasher.update(&msg);
113 let digest = hasher.finalize();
114 let mut dig = [0u8; 32];
115 dig.copy_from_slice(&digest);
116 let sig = self
117 .sign_hash(H256::from(dig))
118 .map_err(|_| RelayClientError::SignerUnavailable)?;
119 Ok(sig_to_hex(sig))
120 }
121 fn sign_eip712_digest(&self, digest_hex: &str) -> Result<String> {
122 let bytes = hex::decode(digest_hex.trim_start_matches("0x"))
124 .map_err(|_| RelayClientError::SignerUnavailable)?;
125 let mut arr = [0u8; 32];
126 arr.copy_from_slice(&bytes);
127 let sig = AbstractSigner::sign_eip712_digest(self, H256::from(arr))
128 .map_err(|_| RelayClientError::SignerUnavailable)?;
129 Ok(sig_to_hex(sig))
130 }
131}
132
133impl builder_relayer_client_rust::builder::create::TypedDataSigner for DummySigner {
134 fn sign_typed_create_proxy(
135 &self,
136 _safe_factory: &str,
137 _chain_id: u64,
138 _payment_token: &str,
139 _payment: &str,
140 _payment_receiver: &str,
141 ) -> Result<String> {
142 let sig = self
144 .sign_hash(H256::zero())
145 .map_err(|_| RelayClientError::SignerUnavailable)?;
146 Ok(sig_to_hex(sig))
147 }
148}
149
150impl builder_relayer_client_rust::builder::create::AbstractSignerForCreate for DummySigner {
151 fn get_address(&self) -> Result<String> {
152 Ok(format!("0x{:x}", self.address()))
153 }
154 fn sign_eip712_digest(&self, digest_hex: &str) -> Result<String> {
155 let bytes = hex::decode(digest_hex.trim_start_matches("0x"))
157 .map_err(|_| RelayClientError::SignerUnavailable)?;
158 let mut arr = [0u8; 32];
159 arr.copy_from_slice(&bytes);
160 let sig = AbstractSigner::sign_eip712_digest(self, H256::from(arr))
161 .map_err(|_| RelayClientError::SignerUnavailable)?;
162 Ok(sig_to_hex(sig))
163 }
164}
165
166fn sig_to_hex(sig: Signature) -> String {
167 let mut r_bytes = [0u8; 32];
169 sig.r.to_big_endian(&mut r_bytes);
170 let mut s_bytes = [0u8; 32];
171 sig.s.to_big_endian(&mut s_bytes);
172 format!(
173 "0x{}{}{:02x}",
174 hex::encode(r_bytes),
175 hex::encode(s_bytes),
176 sig.v
177 )
178}