@@ -20,6 +20,7 @@ use solver_types::{
2020/// This implementation manages a private key locally and uses it to sign
2121/// transactions and messages. It's suitable for development and testing
2222/// environments where key management simplicity is preferred.
23+ #[ derive( Debug ) ]
2324pub struct LocalWallet {
2425 /// The underlying Alloy signer that handles cryptographic operations.
2526 signer : PrivateKeySigner ,
@@ -188,3 +189,185 @@ impl solver_types::ImplementationRegistry for Registry {
188189}
189190
190191impl crate :: AccountRegistry for Registry { }
192+
193+ #[ cfg( test) ]
194+ mod tests {
195+ use super :: * ;
196+ use solver_types:: {
197+ utils:: tests:: builders:: TransactionBuilder , Address , ImplementationRegistry , Transaction ,
198+ } ;
199+ use std:: collections:: HashMap ;
200+
201+ // Test private key (FOR TESTING ONLY!)
202+ const TEST_PRIVATE_KEY : & str =
203+ "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ;
204+ const TEST_PRIVATE_KEY_WITH_PREFIX : & str =
205+ "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" ;
206+ const INVALID_PRIVATE_KEY : & str = "invalid_key" ;
207+ const SHORT_PRIVATE_KEY : & str = "1234" ;
208+
209+ fn create_test_config ( private_key : & str ) -> toml:: Value {
210+ let mut config = HashMap :: new ( ) ;
211+ config. insert (
212+ "private_key" . to_string ( ) ,
213+ toml:: Value :: String ( private_key. to_string ( ) ) ,
214+ ) ;
215+ toml:: Value :: Table ( config. into_iter ( ) . collect ( ) )
216+ }
217+
218+ fn create_test_transaction ( ) -> Transaction {
219+ TransactionBuilder :: new ( ) . gas_price_gwei ( 21 ) . build ( )
220+ }
221+
222+ #[ test]
223+ fn test_local_wallet_new_valid_key ( ) {
224+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
225+ assert ! ( wallet. signer. to_bytes( ) . len( ) == 32 ) ;
226+ }
227+
228+ #[ test]
229+ fn test_local_wallet_new_valid_key_with_prefix ( ) {
230+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY_WITH_PREFIX ) . unwrap ( ) ;
231+ assert ! ( wallet. signer. to_bytes( ) . len( ) == 32 ) ;
232+ }
233+
234+ #[ test]
235+ fn test_local_wallet_new_invalid_key ( ) {
236+ let result = LocalWallet :: new ( INVALID_PRIVATE_KEY ) ;
237+ assert ! ( result. is_err( ) ) ;
238+ assert ! ( matches!( result. unwrap_err( ) , AccountError :: InvalidKey ( _) ) ) ;
239+ }
240+
241+ #[ test]
242+ fn test_local_wallet_get_private_key ( ) {
243+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
244+ let private_key = wallet. get_private_key ( ) ;
245+ let private_key_str = private_key. with_exposed ( |s| s. to_string ( ) ) ;
246+ assert ! ( private_key_str. starts_with( "0x" ) ) ;
247+ assert_eq ! ( private_key_str. len( ) , 66 ) ; // 0x + 64 hex chars
248+ }
249+
250+ #[ test]
251+ fn test_schema_validation_valid_config ( ) {
252+ let config = create_test_config ( TEST_PRIVATE_KEY ) ;
253+ let result = LocalWalletSchema :: validate_config ( & config) ;
254+ assert ! ( result. is_ok( ) ) ;
255+ }
256+
257+ #[ test]
258+ fn test_schema_validation_valid_config_with_prefix ( ) {
259+ let config = create_test_config ( TEST_PRIVATE_KEY_WITH_PREFIX ) ;
260+ let result = LocalWalletSchema :: validate_config ( & config) ;
261+ assert ! ( result. is_ok( ) ) ;
262+ }
263+
264+ #[ test]
265+ fn test_schema_validation_invalid_hex ( ) {
266+ let config = create_test_config ( INVALID_PRIVATE_KEY ) ;
267+ let result = LocalWalletSchema :: validate_config ( & config) ;
268+ assert ! ( result. is_err( ) ) ;
269+ }
270+
271+ #[ test]
272+ fn test_schema_validation_short_key ( ) {
273+ let config = create_test_config ( SHORT_PRIVATE_KEY ) ;
274+ let result = LocalWalletSchema :: validate_config ( & config) ;
275+ assert ! ( result. is_err( ) ) ;
276+ }
277+
278+ #[ test]
279+ fn test_schema_validation_missing_private_key ( ) {
280+ let config = toml:: Value :: Table ( HashMap :: new ( ) . into_iter ( ) . collect ( ) ) ;
281+ let result = LocalWalletSchema :: validate_config ( & config) ;
282+ assert ! ( result. is_err( ) ) ;
283+ }
284+
285+ #[ tokio:: test]
286+ async fn test_account_interface_address ( ) {
287+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
288+ let address = wallet. address ( ) . await . unwrap ( ) ;
289+ assert_eq ! ( address. 0 . len( ) , 20 ) ;
290+ }
291+
292+ #[ tokio:: test]
293+ async fn test_account_interface_sign_transaction ( ) {
294+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
295+ let tx = create_test_transaction ( ) ;
296+ let signature = wallet. sign_transaction ( & tx) . await . unwrap ( ) ;
297+ assert ! ( !signature. 0 . is_empty( ) ) ;
298+ }
299+
300+ #[ tokio:: test]
301+ async fn test_account_interface_sign_transaction_invalid_address ( ) {
302+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
303+ let mut tx = create_test_transaction ( ) ;
304+ tx. to = Some ( Address ( vec ! [ 0u8 ; 19 ] ) ) ; // Invalid address length
305+
306+ let result = wallet. sign_transaction ( & tx) . await ;
307+ assert ! ( result. is_err( ) ) ;
308+ assert ! ( matches!(
309+ result. unwrap_err( ) ,
310+ AccountError :: SigningFailed ( _)
311+ ) ) ;
312+ }
313+
314+ #[ tokio:: test]
315+ async fn test_account_interface_sign_transaction_contract_creation ( ) {
316+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
317+ let mut tx = create_test_transaction ( ) ;
318+ tx. to = None ; // Contract creation
319+
320+ let signature = wallet. sign_transaction ( & tx) . await . unwrap ( ) ;
321+ assert ! ( !signature. 0 . is_empty( ) ) ;
322+ }
323+
324+ #[ tokio:: test]
325+ async fn test_account_interface_sign_message ( ) {
326+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
327+ let message = b"Hello, World!" ;
328+ let signature = wallet. sign_message ( message) . await . unwrap ( ) ;
329+ assert ! ( !signature. 0 . is_empty( ) ) ;
330+ }
331+
332+ #[ test]
333+ fn test_create_account_valid_config ( ) {
334+ let config = create_test_config ( TEST_PRIVATE_KEY ) ;
335+ let account = create_account ( & config) . unwrap ( ) ;
336+ assert ! ( !account. get_private_key( ) . with_exposed( |s| s. is_empty( ) ) ) ;
337+ }
338+
339+ #[ test]
340+ fn test_create_account_invalid_config ( ) {
341+ let config = create_test_config ( INVALID_PRIVATE_KEY ) ;
342+ let result = create_account ( & config) ;
343+ assert ! ( result. is_err( ) ) ;
344+ }
345+
346+ #[ test]
347+ fn test_create_account_missing_private_key ( ) {
348+ let config = toml:: Value :: Table ( HashMap :: new ( ) . into_iter ( ) . collect ( ) ) ;
349+ let result = create_account ( & config) ;
350+ assert ! ( result. is_err( ) ) ;
351+ }
352+
353+ #[ test]
354+ fn test_registry_name ( ) {
355+ assert_eq ! ( Registry :: NAME , "local" ) ;
356+ }
357+
358+ #[ test]
359+ fn test_registry_factory ( ) {
360+ let factory = Registry :: factory ( ) ;
361+ let config = create_test_config ( TEST_PRIVATE_KEY ) ;
362+ let account = factory ( & config) . unwrap ( ) ;
363+ assert ! ( !account. get_private_key( ) . with_exposed( |s| s. is_empty( ) ) ) ;
364+ }
365+
366+ #[ test]
367+ fn test_config_schema_interface ( ) {
368+ let wallet = LocalWallet :: new ( TEST_PRIVATE_KEY ) . unwrap ( ) ;
369+ let schema = wallet. config_schema ( ) ;
370+ let config = create_test_config ( TEST_PRIVATE_KEY ) ;
371+ assert ! ( schema. validate( & config) . is_ok( ) ) ;
372+ }
373+ }
0 commit comments