11"use client" ;
2- import { Suspense , lazy , useCallback } from "react" ;
2+ import { Suspense , lazy , useCallback , useEffect , useState } from "react" ;
33import type { Chain } from "../../../../../chains/types.js" ;
44import type { ThirdwebClient } from "../../../../../client/client.js" ;
5+ import { isEcosystemWallet } from "../../../../../wallets/ecosystem/is-ecosystem-wallet.js" ;
6+ import type { Profile } from "../../../../../wallets/in-app/core/authentication/types.js" ;
7+ import { getProfiles } from "../../../../../wallets/in-app/web/lib/auth/index.js" ;
58import type { Wallet } from "../../../../../wallets/interfaces/wallet.js" ;
69import type { SmartWalletOptions } from "../../../../../wallets/smart/types.js" ;
710import type { WalletId } from "../../../../../wallets/wallet-types.js" ;
@@ -13,11 +16,13 @@ import { useActiveAccount } from "../../../../core/hooks/wallets/useActiveAccoun
1316import { useActiveWallet } from "../../../../core/hooks/wallets/useActiveWallet.js" ;
1417import { useSetActiveWallet } from "../../../../core/hooks/wallets/useSetActiveWallet.js" ;
1518import { useConnectionManager } from "../../../../core/providers/connection-manager.js" ;
19+ import { useProfiles } from "../../../hooks/wallets/useProfiles.js" ;
1620import { useSetSelectionData } from "../../../providers/wallet-ui-states-provider.js" ;
1721import { LoadingScreen } from "../../../wallets/shared/LoadingScreen.js" ;
1822import { WalletSelector } from "../WalletSelector.js" ;
1923import { onModalUnmount , reservedScreens } from "../constants.js" ;
2024import type { ConnectLocale } from "../locale/types.js" ;
25+ import { LinkProfileScreen } from "../screens/LinkProfileScreen.js" ;
2126import { SignatureScreen } from "../screens/SignatureScreen.js" ;
2227import { StartScreen } from "../screens/StartScreen.js" ;
2328import type { WelcomeScreen } from "../screens/types.js" ;
@@ -84,45 +89,147 @@ export const ConnectModalContent = (props: {
8489 const showSignatureScreen = siweAuth . requiresAuth && ! siweAuth . isLoggedIn ;
8590 const connectionManager = useConnectionManager ( ) ;
8691
92+ // state to hold wallet awaiting email link
93+ const [ pendingWallet , setPendingWallet ] = useState < Wallet | undefined > ( ) ;
94+
95+ // get profiles to observe email linking
96+ const profilesQuery = useProfiles ( { client : props . client } ) ;
97+
8798 const handleConnected = useCallback (
88- ( wallet : Wallet ) => {
89- if ( shouldSetActive ) {
90- setActiveWallet ( wallet ) ;
91- } else {
92- connectionManager . addConnectedWallet ( wallet ) ;
93- }
99+ async ( wallet : Wallet ) => {
100+ // we will only set active wallet and call onConnect once requirements are met
101+ const finalizeConnection = ( w : Wallet ) => {
102+ if ( shouldSetActive ) {
103+ setActiveWallet ( w ) ;
104+ } else {
105+ connectionManager . addConnectedWallet ( w ) ;
106+ }
107+
108+ if ( props . onConnect ) {
109+ props . onConnect ( w ) ;
110+ }
111+
112+ onModalUnmount ( ( ) => {
113+ setSelectionData ( { } ) ;
114+ setScreen ( initialScreen ) ;
115+ setModalVisibility ( true ) ;
116+ } ) ;
117+ } ;
118+
119+ // ----------------------------------------------------------------
120+ // Enforce required profile linking (currently only "email")
121+ // ----------------------------------------------------------------
122+ type WalletConfig = {
123+ auth ?: {
124+ required ?: string [ ] ;
125+ } ;
126+ partnerId ?: string ;
127+ } ;
128+
129+ const walletWithConfig = wallet as unknown as {
130+ getConfig ?: ( ) => WalletConfig | undefined ;
131+ } ;
132+
133+ const walletConfig = walletWithConfig . getConfig
134+ ? walletWithConfig . getConfig ( )
135+ : undefined ;
136+ const required = walletConfig ?. auth ?. required as string [ ] | undefined ;
137+ const requiresEmail = required ?. includes ( "email" ) ;
94138
95- if ( props . onConnect ) {
96- props . onConnect ( wallet ) ;
139+ console . log ( "wallet" , walletConfig ) ;
140+
141+ console . log ( "requiresEmail" , requiresEmail ) ;
142+
143+ if ( requiresEmail ) {
144+ try {
145+ const ecosystem = isEcosystemWallet ( wallet )
146+ ? { id : wallet . id , partnerId : walletConfig ?. partnerId }
147+ : undefined ;
148+
149+ const profiles = await getProfiles ( {
150+ client : props . client ,
151+ ecosystem,
152+ } ) ;
153+
154+ console . log ( "profiles" , profiles ) ;
155+
156+ const hasEmail = ( profiles as Profile [ ] ) . some (
157+ ( p ) => ! ! p . details . email ,
158+ ) ;
159+
160+ console . log ( "hasEmail" , hasEmail ) ;
161+
162+ if ( ! hasEmail ) {
163+ setPendingWallet ( wallet ) ;
164+ setScreen ( reservedScreens . linkProfile ) ;
165+ return ; // defer activation until linked
166+ }
167+ } catch ( err ) {
168+ console . error ( "Failed to fetch profiles for required linking" , err ) ;
169+ // if fetching profiles fails, just continue the normal flow
170+ }
97171 }
98172
99- onModalUnmount ( ( ) => {
100- setSelectionData ( { } ) ;
101- setModalVisibility ( true ) ;
102- } ) ;
173+ // ----------------------------------------------------------------
174+ // Existing behavior (sign in step / close modal)
175+ // ----------------------------------------------------------------
103176
104- // show sign in screen if required
105177 if ( showSignatureScreen ) {
106178 setScreen ( reservedScreens . signIn ) ;
107179 } else {
108- setScreen ( initialScreen ) ;
180+ finalizeConnection ( wallet ) ;
109181 onClose ?.( ) ;
110182 }
111183 } ,
112184 [
113- setModalVisibility ,
114- onClose ,
115- props . onConnect ,
185+ shouldSetActive ,
116186 setActiveWallet ,
117- showSignatureScreen ,
118- setScreen ,
187+ connectionManager ,
188+ props . onConnect ,
119189 setSelectionData ,
120- shouldSetActive ,
190+ setModalVisibility ,
191+ props . client ,
192+ setScreen ,
193+ showSignatureScreen ,
121194 initialScreen ,
122- connectionManager ,
195+ onClose ,
123196 ] ,
124197 ) ;
125198
199+ // Effect to watch for email linking completion
200+ useEffect ( ( ) => {
201+ if ( ! pendingWallet ) {
202+ return ;
203+ }
204+ const profiles = profilesQuery . data ;
205+ if ( ! profiles ) {
206+ return ;
207+ }
208+ const hasEmail = profiles . some ( ( p ) => ! ! p . details . email ) ;
209+ if ( hasEmail ) {
210+ // finalize connection now
211+ if ( shouldSetActive ) {
212+ setActiveWallet ( pendingWallet ) ;
213+ } else {
214+ connectionManager . addConnectedWallet ( pendingWallet ) ;
215+ }
216+ props . onConnect ?.( pendingWallet ) ;
217+ setPendingWallet ( undefined ) ;
218+ setScreen ( initialScreen ) ;
219+ onClose ?.( ) ;
220+ }
221+ } , [
222+ profilesQuery . data ,
223+ pendingWallet ,
224+ shouldSetActive ,
225+ setActiveWallet ,
226+ connectionManager ,
227+ props . onConnect ,
228+ setScreen ,
229+ initialScreen ,
230+ onClose ,
231+ ] ) ;
232+
126233 const handleBack = useCallback ( ( ) => {
127234 setSelectionData ( { } ) ;
128235 setScreen ( initialScreen ) ;
@@ -145,7 +252,9 @@ export const ConnectModalContent = (props: {
145252 onShowAll = { ( ) => {
146253 setScreen ( reservedScreens . showAll ) ;
147254 } }
148- done = { handleConnected }
255+ done = { async ( w ) => {
256+ await handleConnected ( w ) ;
257+ } }
149258 goBack = { props . wallets . length > 1 ? handleBack : undefined }
150259 setModalVisibility = { setModalVisibility }
151260 client = { props . client }
@@ -195,8 +304,8 @@ export const ConnectModalContent = (props: {
195304 < SmartConnectUI
196305 key = { wallet . id }
197306 accountAbstraction = { props . accountAbstraction }
198- done = { ( smartWallet ) => {
199- handleConnected ( smartWallet ) ;
307+ done = { async ( smartWallet ) => {
308+ await handleConnected ( smartWallet ) ;
200309 } }
201310 personalWallet = { wallet }
202311 onBack = { goBack }
@@ -217,8 +326,8 @@ export const ConnectModalContent = (props: {
217326 key = { wallet . id }
218327 wallet = { wallet }
219328 onBack = { goBack }
220- done = { ( ) => {
221- handleConnected ( wallet ) ;
329+ done = { async ( ) => {
330+ await handleConnected ( wallet ) ;
222331 } }
223332 setModalVisibility = { props . setModalVisibility }
224333 chain = { props . chain }
@@ -245,6 +354,16 @@ export const ConnectModalContent = (props: {
245354 />
246355 ) ;
247356
357+ const linkProfileScreen = (
358+ < LinkProfileScreen
359+ onBack = { handleBack }
360+ locale = { props . connectLocale }
361+ client = { props . client }
362+ walletConnect = { props . walletConnect }
363+ wallet = { pendingWallet }
364+ />
365+ ) ;
366+
248367 return (
249368 < ScreenSetupContext . Provider value = { props . screenSetup } >
250369 { props . size === "wide" ? (
@@ -256,6 +375,7 @@ export const ConnectModalContent = (props: {
256375 { screen === reservedScreens . main && getStarted }
257376 { screen === reservedScreens . getStarted && getStarted }
258377 { screen === reservedScreens . showAll && showAll }
378+ { screen === reservedScreens . linkProfile && linkProfileScreen }
259379 { typeof screen !== "string" && getWalletUI ( screen ) }
260380 </ >
261381 }
@@ -266,6 +386,7 @@ export const ConnectModalContent = (props: {
266386 { screen === reservedScreens . main && walletList }
267387 { screen === reservedScreens . getStarted && getStarted }
268388 { screen === reservedScreens . showAll && showAll }
389+ { screen === reservedScreens . linkProfile && linkProfileScreen }
269390 { typeof screen !== "string" && getWalletUI ( screen ) }
270391 </ ConnectModalCompactLayout >
271392 ) }
0 commit comments