@@ -2,6 +2,9 @@ use crate::error::WasmSdkError;
22use crate :: sdk:: WasmSdk ;
33use dash_sdk:: dpp:: document:: { Document , DocumentV0Getters } ;
44use dash_sdk:: dpp:: identity:: accessors:: IdentityGettersV0 ;
5+ use dash_sdk:: dpp:: identity:: identity_public_key:: accessors:: v0:: IdentityPublicKeyGettersV0 ;
6+ use dash_sdk:: dpp:: identity:: signer:: Signer ;
7+ use dash_sdk:: dpp:: identity:: { Purpose , SecurityLevel } ;
58use dash_sdk:: dpp:: prelude:: Identifier ;
69use dash_sdk:: platform:: dpns_usernames:: {
710 convert_to_homograph_safe_chars, is_contested_username, is_valid_username,
@@ -76,6 +79,81 @@ impl WasmSdk {
7679 } ) ?
7780 . clone ( ) ;
7881
82+ // Validate the key meets DPNS requirements
83+ let key_purpose = identity_public_key. purpose ( ) ;
84+ let key_security_level = identity_public_key. security_level ( ) ;
85+
86+ // Check purpose
87+ if key_purpose != Purpose :: AUTHENTICATION {
88+ return Err ( WasmSdkError :: invalid_argument ( format ! (
89+ "Cannot register DPNS name with key ID {}: key has purpose {:?} but AUTHENTICATION is required.\n \
90+ Use a key with purpose AUTHENTICATION (usually keys 0-2).",
91+ public_key_id, key_purpose
92+ ) ) ) ;
93+ }
94+
95+ // Check security level
96+ if key_security_level != SecurityLevel :: CRITICAL
97+ && key_security_level != SecurityLevel :: HIGH
98+ {
99+ let available_keys: Vec < String > = identity
100+ . public_keys ( )
101+ . iter ( )
102+ . filter_map ( |( key_id, k) | {
103+ if k. purpose ( ) == Purpose :: AUTHENTICATION
104+ && ( k. security_level ( ) == SecurityLevel :: CRITICAL
105+ || k. security_level ( ) == SecurityLevel :: HIGH )
106+ {
107+ let level_name = if k. security_level ( ) == SecurityLevel :: CRITICAL {
108+ "CRITICAL"
109+ } else {
110+ "HIGH"
111+ } ;
112+ Some (
113+ String :: from ( " Key " )
114+ + & key_id. to_string ( )
115+ + ": "
116+ + level_name
117+ + " security level" ,
118+ )
119+ } else {
120+ None
121+ }
122+ } )
123+ . collect ( ) ;
124+
125+ let suggestion = if available_keys. is_empty ( ) {
126+ "No suitable keys found in this identity." . to_string ( )
127+ } else {
128+ format ! ( "Try one of these keys:\n {}" , available_keys. join( "\n " ) )
129+ } ;
130+
131+ return Err ( WasmSdkError :: invalid_argument ( format ! (
132+ "Cannot register DPNS name with key ID {}: key has {:?} security level but CRITICAL or HIGH is required.\n \
133+ \n \
134+ DPNS registration requires a key with:\n \
135+ - Purpose: AUTHENTICATION\n \
136+ - Security Level: CRITICAL or HIGH (not MASTER)\n \
137+ \n \
138+ {}",
139+ public_key_id, key_security_level, suggestion
140+ ) ) ) ;
141+ }
142+
143+ // Validate private key matches public key
144+ if !signer. can_sign_with ( & identity_public_key) {
145+ return Err ( WasmSdkError :: invalid_argument ( format ! (
146+ "The provided private key does not match public key ID {}.\n \
147+ \n \
148+ Public key {} details:\n \
149+ - Security Level: {:?}\n \
150+ - Purpose: {:?}\n \
151+ \n \
152+ Please verify you're using the correct private key (WIF) for this key.",
153+ public_key_id, public_key_id, key_security_level, key_purpose
154+ ) ) ) ;
155+ }
156+
79157 // Store the JS callback in a thread-local variable that we can access from the closure
80158 thread_local ! {
81159 static PREORDER_CALLBACK : std:: cell:: RefCell <Option <js_sys:: Function >> = const { std:: cell:: RefCell :: new( None ) } ;
0 commit comments