@@ -158,33 +158,39 @@ export class VaultController {
158158 /**
159159 * Sync public key to eVault core via wallet-sdk.
160160 * SDK checks /whois and skips PATCH if current key already in certs; otherwise PATCHes /public-key.
161+ * Returns true if the sync succeeded, false otherwise.
161162 */
162- async syncPublicKey ( eName : string ) : Promise < void > {
163+ async syncPublicKey (
164+ eName : string ,
165+ keyId = "default" ,
166+ context = "onboarding" ,
167+ ) : Promise < boolean > {
163168 if ( ! this . #walletSdkAdapter) {
164169 console . warn (
165170 "Wallet SDK adapter not available, cannot sync public key" ,
166171 ) ;
167- return ;
172+ return false ;
168173 }
169174 const vault = await this . vault ;
170175 if ( ! vault ?. uri ) {
171176 console . warn ( "No vault URI available, cannot sync public key" ) ;
172- return ;
177+ return false ;
173178 }
174179 try {
175180 await syncPublicKeyToEvault ( this . #walletSdkAdapter, {
176181 evaultUri : vault . uri ,
177182 eName,
178- keyId : "default" ,
179- context : "onboarding" ,
183+ keyId,
184+ context,
180185 authToken : PUBLIC_EID_WALLET_TOKEN || null ,
181186 registryUrl : PUBLIC_REGISTRY_URL ,
182187 } ) ;
183188 localStorage . setItem ( `publicKeySaved_${ eName } ` , "true" ) ;
184189 console . log ( `Public key synced successfully for ${ eName } ` ) ;
190+ return true ;
185191 } catch ( error ) {
186192 console . error ( "Failed to sync public key:" , error ) ;
187- // Don't throw - this is a non-critical operation
193+ return false ;
188194 }
189195 }
190196
@@ -681,6 +687,64 @@ export class VaultController {
681687 }
682688 }
683689
690+ /**
691+ * Fetch the public key(s) currently registered in the eVault via /whois.
692+ * Decodes JWT payloads from keyBindingCertificates without full verification
693+ * — we only need the public key strings for local comparison.
694+ * Returns empty array on any failure (network, parse, etc).
695+ */
696+ async fetchRegisteredPublicKeys ( eName : string ) : Promise < string [ ] > {
697+ const vault = await this . vault ;
698+ if ( ! vault ?. uri ) {
699+ console . warn (
700+ "No vault URI available, cannot fetch registered keys" ,
701+ ) ;
702+ return [ ] ;
703+ }
704+
705+ try {
706+ const base = vault . uri . replace ( / \/ $ / , "" ) ;
707+ const whoisUrl = new URL ( "/whois" , base ) . toString ( ) ;
708+ const headers : Record < string , string > = { "X-ENAME" : eName } ;
709+ if ( PUBLIC_EID_WALLET_TOKEN ) {
710+ headers . Authorization = `Bearer ${ PUBLIC_EID_WALLET_TOKEN } ` ;
711+ }
712+
713+ const response = await axios . get ( whoisUrl , {
714+ headers,
715+ timeout : 5000 ,
716+ } ) ;
717+ const certs = response . data ?. keyBindingCertificates ;
718+ if ( ! Array . isArray ( certs ) || certs . length === 0 ) {
719+ return [ ] ;
720+ }
721+
722+ const publicKeys : string [ ] = [ ] ;
723+ for ( const jwt of certs ) {
724+ try {
725+ const parts = ( jwt as string ) . split ( "." ) ;
726+ if ( parts . length !== 3 ) continue ;
727+ // Decode base64url payload (add padding for atob)
728+ let b64 = parts [ 1 ] . replace ( / - / g, "+" ) . replace ( / _ / g, "/" ) ;
729+ while ( b64 . length % 4 !== 0 ) b64 += "=" ;
730+ const payload = JSON . parse ( atob ( b64 ) ) as {
731+ ename ?: string ;
732+ publicKey ?: string ;
733+ } ;
734+ if ( payload . ename === eName && payload . publicKey ) {
735+ publicKeys . push ( payload . publicKey ) ;
736+ }
737+ } catch {
738+ // skip malformed certs
739+ }
740+ }
741+ return publicKeys ;
742+ } catch ( error ) {
743+ console . error ( "Failed to fetch registered public keys:" , error ) ;
744+ return [ ] ;
745+ }
746+ }
747+
684748 async clear ( ) {
685749 await this . #store. delete ( "vault" ) ;
686750 }
0 commit comments