@@ -31,6 +31,8 @@ pub use response::*;
3131use crate :: { constants:: ID_REGEX , models:: SecretString } ;
3232use secrets:: SecretVec ;
3333use serde:: { Deserialize , Serialize , Serializer } ;
34+ use solana_sdk:: pubkey:: Pubkey ;
35+ use std:: str:: FromStr ;
3436use utoipa:: ToSchema ;
3537use validator:: Validate ;
3638
@@ -195,8 +197,8 @@ pub struct CdpSignerConfig {
195197 message = "API Wallet Secret cannot be empty"
196198 ) ) ]
197199 pub wallet_secret : SecretString ,
198- pub evm_account_address : Option < String > ,
199- pub solana_account_address : Option < String > ,
200+ # [ validate ( length ( min = 1 , message = "Account address cannot be empty" ) ) ]
201+ pub account_address : String ,
200202}
201203
202204/// Google Cloud KMS service account configuration
@@ -262,47 +264,31 @@ fn validate_secret_string(secret: &SecretString) -> Result<(), validator::Valida
262264
263265/// Custom validator for CDP signer configuration
264266fn validate_cdp_config ( config : & CdpSignerConfig ) -> Result < ( ) , validator:: ValidationError > {
265- // Check that at least one address is provided
266- if config. evm_account_address . is_none ( ) && config. solana_account_address . is_none ( ) {
267- let mut error = validator:: ValidationError :: new ( "missing_addresses" ) ;
268- error. message = Some ( "at least one CDP address (evm_account_address or solana_account_address) must be provided" . into ( ) ) ;
269- return Err ( error) ;
270- }
267+ let addr = & config. account_address ;
271268
272- // Validate EVM address format if provided
273- if let Some ( ref evm_addr ) = config . evm_account_address {
274- if !evm_addr . starts_with ( "0x" ) || evm_addr . len ( ) != 42 {
269+ // Check if it's an EVM address (0x-prefixed hex)
270+ if addr . starts_with ( "0x" ) {
271+ if addr . len ( ) != 42 {
275272 let mut error = validator:: ValidationError :: new ( "invalid_evm_address_format" ) ;
276273 error. message = Some (
277- "evm_account_address must be a valid 0x-prefixed 40-character hex string" . into ( ) ,
274+ "EVM account address must be a valid 0x-prefixed 40-character hex string" . into ( ) ,
278275 ) ;
279276 return Err ( error) ;
280277 }
281- // Check if the hex part is valid
282- if !evm_addr[ 2 ..] . chars ( ) . all ( |c| c. is_ascii_hexdigit ( ) ) {
283- let mut error = validator:: ValidationError :: new ( "invalid_evm_address_hex" ) ;
284- error. message = Some ( "evm_account_address contains invalid hex characters" . into ( ) ) ;
285- return Err ( error) ;
286- }
287- }
288278
289- // Validate Solana address format if provided (Base58, typically 32-44 chars)
290- if let Some ( ref solana_addr ) = config . solana_account_address {
291- // Basic length check for Solana addresses
292- if solana_addr . len ( ) < 32 || solana_addr . len ( ) > 44 {
293- let mut error = validator :: ValidationError :: new ( "invalid_solana_address_length" ) ;
294- error . message = Some ( "solana_account_address must be between 32-44 characters" . into ( ) ) ;
295- return Err ( error ) ;
279+ // Check if the hex part is valid
280+ if let Some ( end ) = addr . strip_prefix ( "0x" ) {
281+ if !end . chars ( ) . all ( |c| c . is_ascii_hexdigit ( ) ) {
282+ let mut error = validator :: ValidationError :: new ( "invalid_evm_address_hex" ) ;
283+ error. message = Some ( "EVM account address contains invalid hex characters" . into ( ) ) ;
284+ return Err ( error ) ;
285+ }
296286 }
297- // Check for Base58 character set (no 0, O, I, l)
298- if !solana_addr
299- . chars ( )
300- . all ( |c| c. is_ascii_alphanumeric ( ) && c != '0' && c != 'O' && c != 'I' && c != 'l' )
301- {
302- let mut error = validator:: ValidationError :: new ( "invalid_solana_address_charset" ) ;
303- error. message = Some (
304- "solana_account_address contains invalid characters (must be valid Base58)" . into ( ) ,
305- ) ;
287+ } else {
288+ // Assume it's a Solana address - validate using Pubkey::from_str
289+ if Pubkey :: from_str ( addr) . is_err ( ) {
290+ let mut error = validator:: ValidationError :: new ( "invalid_solana_address" ) ;
291+ error. message = Some ( "Invalid Solana account address format" . into ( ) ) ;
306292 return Err ( error) ;
307293 }
308294 }
@@ -957,8 +943,7 @@ mod tests {
957943 api_key_id : "test-api-key" . to_string ( ) ,
958944 api_key_secret : SecretString :: new ( "secret" ) ,
959945 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
960- evm_account_address : Some ( "0x742d35Cc6634C0532925a3b844Bc454e4438f44f" . to_string ( ) ) ,
961- solana_account_address : None ,
946+ account_address : "0x742d35Cc6634C0532925a3b844Bc454e4438f44f" . to_string ( ) ,
962947 } ;
963948 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
964949 assert ! ( signer. validate( ) . is_ok( ) ) ;
@@ -971,48 +956,28 @@ mod tests {
971956 api_key_id : "test-api-key" . to_string ( ) ,
972957 api_key_secret : SecretString :: new ( "secret" ) ,
973958 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
974- evm_account_address : None ,
975- solana_account_address : Some (
976- "6s7RsvzcdXFJi1tXeDoGfSKZFzN3juVt9fTar6WEhEm2" . to_string ( ) ,
977- ) ,
978- } ;
979- let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
980- assert ! ( signer. validate( ) . is_ok( ) ) ;
981- assert_eq ! ( signer. signer_type( ) , SignerType :: Cdp ) ;
982- }
983-
984- #[ test]
985- fn test_valid_cdp_signer_with_both_addresses ( ) {
986- let config = CdpSignerConfig {
987- api_key_id : "test-api-key" . to_string ( ) ,
988- api_key_secret : SecretString :: new ( "secret" ) ,
989- wallet_secret : SecretString :: new ( "wallet-secret" ) ,
990- evm_account_address : Some ( "0x742d35Cc6634C0532925a3b844Bc454e4438f44f" . to_string ( ) ) ,
991- solana_account_address : Some (
992- "6s7RsvzcdXFJi1tXeDoGfSKZFzN3juVt9fTar6WEhEm2" . to_string ( ) ,
993- ) ,
959+ account_address : "6s7RsvzcdXFJi1tXeDoGfSKZFzN3juVt9fTar6WEhEm2" . to_string ( ) ,
994960 } ;
995961 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
996962 assert ! ( signer. validate( ) . is_ok( ) ) ;
997963 assert_eq ! ( signer. signer_type( ) , SignerType :: Cdp ) ;
998964 }
999965
1000966 #[ test]
1001- fn test_invalid_cdp_signer_missing_addresses ( ) {
967+ fn test_invalid_cdp_signer_empty_address ( ) {
1002968 let config = CdpSignerConfig {
1003969 api_key_id : "test-api-key" . to_string ( ) ,
1004970 api_key_secret : SecretString :: new ( "secret" ) ,
1005971 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
1006- evm_account_address : None ,
1007- solana_account_address : None ,
972+ account_address : "" . to_string ( ) ,
1008973 } ;
1009974 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
1010975 let result = signer. validate ( ) ;
1011976 assert ! ( result. is_err( ) ) ;
1012977 if let Err ( SignerValidationError :: InvalidConfig ( msg) ) = result {
1013- assert ! ( msg. contains( "at least one CDP address " ) ) ;
978+ assert ! ( msg. contains( "Account address cannot be empty " ) ) ;
1014979 } else {
1015- panic ! ( "Expected InvalidConfig error for missing addresses " ) ;
980+ panic ! ( "Expected InvalidConfig error for empty address " ) ;
1016981 }
1017982 }
1018983
@@ -1022,14 +987,13 @@ mod tests {
1022987 api_key_id : "test-api-key" . to_string ( ) ,
1023988 api_key_secret : SecretString :: new ( "secret" ) ,
1024989 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
1025- evm_account_address : Some ( "invalid-address" . to_string ( ) ) ,
1026- solana_account_address : None ,
990+ account_address : "0xinvalid-address" . to_string ( ) ,
1027991 } ;
1028992 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
1029993 let result = signer. validate ( ) ;
1030994 assert ! ( result. is_err( ) ) ;
1031995 if let Err ( SignerValidationError :: InvalidConfig ( msg) ) = result {
1032- assert ! ( msg. contains( "evm_account_address must be a valid 0x-prefixed" ) ) ;
996+ assert ! ( msg. contains( "EVM account address must be a valid 0x-prefixed" ) ) ;
1033997 } else {
1034998 panic ! ( "Expected InvalidConfig error for bad EVM address" ) ;
1035999 }
@@ -1041,14 +1005,13 @@ mod tests {
10411005 api_key_id : "test-api-key" . to_string ( ) ,
10421006 api_key_secret : SecretString :: new ( "secret" ) ,
10431007 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
1044- evm_account_address : None ,
1045- solana_account_address : Some ( "invalid" . to_string ( ) ) ,
1008+ account_address : "invalid" . to_string ( ) ,
10461009 } ;
10471010 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
10481011 let result = signer. validate ( ) ;
10491012 assert ! ( result. is_err( ) ) ;
10501013 if let Err ( SignerValidationError :: InvalidConfig ( msg) ) = result {
1051- assert ! ( msg. contains( "solana_account_address must be between 32-44 characters " ) ) ;
1014+ assert ! ( msg. contains( "Invalid Solana account address format " ) ) ;
10521015 } else {
10531016 panic ! ( "Expected InvalidConfig error for bad Solana address" ) ;
10541017 }
@@ -1060,14 +1023,13 @@ mod tests {
10601023 api_key_id : "test-api-key" . to_string ( ) ,
10611024 api_key_secret : SecretString :: new ( "secret" ) ,
10621025 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
1063- evm_account_address : Some ( "0x742d35Cc6634C0532925a3b844Bc454e4438f44" . to_string ( ) ) , // Too short
1064- solana_account_address : None ,
1026+ account_address : "0x742d35Cc6634C0532925a3b844Bc454e4438f44" . to_string ( ) , // Too short
10651027 } ;
10661028 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
10671029 let result = signer. validate ( ) ;
10681030 assert ! ( result. is_err( ) ) ;
10691031 if let Err ( SignerValidationError :: InvalidConfig ( msg) ) = result {
1070- assert ! ( msg. contains( "evm_account_address must be a valid 0x-prefixed" ) ) ;
1032+ assert ! ( msg. contains( "EVM account address must be a valid 0x-prefixed" ) ) ;
10711033 } else {
10721034 panic ! ( "Expected InvalidConfig error for wrong EVM address format" ) ;
10731035 }
@@ -1079,16 +1041,13 @@ mod tests {
10791041 api_key_id : "test-api-key" . to_string ( ) ,
10801042 api_key_secret : SecretString :: new ( "secret" ) ,
10811043 wallet_secret : SecretString :: new ( "wallet-secret" ) ,
1082- evm_account_address : None ,
1083- solana_account_address : Some (
1084- "6s7RsvzcdXFJi1tXeDoGfSKZFzN3juVt9fTar6WEhEm0" . to_string ( ) ,
1085- ) , // Contains '0' which is invalid in Base58
1044+ account_address : "6s7RsvzcdXFJi1tXeDoGfSKZFzN3juVt9fTar6WEhEm0" . to_string ( ) , // Contains '0' which is invalid in Base58
10861045 } ;
10871046 let signer = Signer :: new ( "cdp-signer" . to_string ( ) , SignerConfig :: Cdp ( config) ) ;
10881047 let result = signer. validate ( ) ;
10891048 assert ! ( result. is_err( ) ) ;
10901049 if let Err ( SignerValidationError :: InvalidConfig ( msg) ) = result {
1091- assert ! ( msg. contains( "solana_account_address contains invalid characters " ) ) ;
1050+ assert ! ( msg. contains( "Invalid Solana account address format " ) ) ;
10921051 } else {
10931052 panic ! ( "Expected InvalidConfig error for wrong Solana address charset" ) ;
10941053 }
0 commit comments