@@ -571,6 +571,59 @@ export class Web3NonCustodialProvider {
571571 } ;
572572 }
573573
574+ /**
575+ * Sends OTP to email address
576+ * @param email - The email address to send OTP to
577+ * @returns Promise that resolves when OTP is sent
578+ */
579+ async sendEmailOtp ( email : string ) : Promise < { error : Error | null } > {
580+ const res = await fetch ( this . appOrigin + "/api/auth/email/send-otp" , {
581+ method : "POST" ,
582+ headers : { "Content-Type" : "application/json" } ,
583+ body : JSON . stringify ( { email, projectId : this . projectId } ) ,
584+ } ) ;
585+
586+ if ( ! res . ok ) {
587+ const data = await res . json ( ) ;
588+ return { error : new Error ( data . error ) } ;
589+ }
590+
591+ return { error : null } ;
592+ }
593+
594+ /**
595+ * Verifies OTP and stores JWT (same pattern as OAuth callback)
596+ * @param email - The email address used to send OTP
597+ * @param code - The 6-digit OTP code
598+ * @returns User data on success, error on failure
599+ */
600+ async verifyEmailOtp (
601+ email : string ,
602+ code : string ,
603+ ) : Promise <
604+ | { data : Web3NonCustodialProviderUser ; error : null }
605+ | { data : null ; error : Error }
606+ > {
607+ const res = await fetch ( this . appOrigin + "/api/auth/email/verify-otp" , {
608+ method : "POST" ,
609+ headers : { "Content-Type" : "application/json" } ,
610+ body : JSON . stringify ( { email, code, projectId : this . projectId } ) ,
611+ } ) ;
612+
613+ if ( ! res . ok ) {
614+ const data = await res . json ( ) ;
615+ return { data : null , error : new Error ( data . error ) } ;
616+ }
617+
618+ const { token } = await res . json ( ) ;
619+
620+ // Store JWT same way as OAuth flow
621+ await this . putInStorage < AuthJwtLocationObject > ( AUTH_KEY , { jwt : token } ) ;
622+
623+ // Return user data same way as getUser()
624+ return this . getUser ( ) ;
625+ }
626+
574627 private async putInStorage < ObjectType extends object > (
575628 key : string ,
576629 data : ObjectType ,
0 commit comments