@@ -6,6 +6,7 @@ import { publicRoutes } from "@/data/public-routes";
66import { api } from "@/utils/api" ;
77import useUser from "@/hooks/useUser" ;
88import { useUserStore } from "@/lib/zustand/user" ;
9+ import { normalizeAddressToBech32 } from "@/utils/addressCompatibility" ;
910import useAppWallet from "@/hooks/useAppWallet" ;
1011import useUTXOS from "@/hooks/useUTXOS" ;
1112import useMeshWallet from "@/hooks/useMeshWallet" ;
@@ -102,7 +103,11 @@ export default function RootLayout({
102103 // 1.9 IWallet bridge — used for getDRep(), which the react 2.0 wallet lacks.
103104 const { wallet : meshWallet } = useMeshWallet ( ) ;
104105 const { state : walletState , connectedWalletInstance } = useWalletContext ( ) ;
105- const address = useAddress ( ) ;
106+ // react-2.0's useAddress can return hex-encoded address bytes; user records
107+ // and sessions are keyed by bech32. Normalize once at the source so every
108+ // consumer below (store sync, session check) uses the bech32 form.
109+ const rawAddress = useAddress ( ) ;
110+ const address = rawAddress ? normalizeAddressToBech32 ( rawAddress ) : rawAddress ;
106111 const { user, isLoading : isLoadingUser } = useUser ( ) ;
107112 const router = useRouter ( ) ;
108113 const { appWallet } = useAppWallet ( ) ;
@@ -111,6 +116,7 @@ export default function RootLayout({
111116
112117 const userAddress = useUserStore ( ( state ) => state . userAddress ) ;
113118 const setUserAddress = useUserStore ( ( state ) => state . setUserAddress ) ;
119+ const reauthNonce = useUserStore ( ( state ) => state . reauthNonce ) ;
114120 const ctx = api . useUtils ( ) ;
115121
116122 // State for wallet authorization modal
@@ -257,15 +263,15 @@ export default function RootLayout({
257263 activeWallet . getUsedAddresses ( )
258264 . then ( ( addresses ) => {
259265 if ( addresses && addresses . length > 0 ) {
260- setUserAddress ( addresses [ 0 ] ! ) ;
266+ setUserAddress ( normalizeAddressToBech32 ( addresses [ 0 ] ! ) ) ;
261267 fetchingAddressRef . current = false ;
262268 } else {
263269 return activeWallet . getUnusedAddresses ( ) ;
264270 }
265271 } )
266272 . then ( ( addresses ) => {
267273 if ( addresses && addresses . length > 0 && ! userAddress ) {
268- setUserAddress ( addresses [ 0 ] ! ) ;
274+ setUserAddress ( normalizeAddressToBech32 ( addresses [ 0 ] ! ) ) ;
269275 }
270276 fetchingAddressRef . current = false ;
271277 } )
@@ -398,6 +404,21 @@ export default function RootLayout({
398404 // Don't refetch here - let the natural query refetch handle it if needed
399405 } , [ ] ) ;
400406
407+ // Manual re-authorization: when the user is connected but never got a
408+ // session (e.g. the auto-authorize failed/was cancelled), hasCheckedSession
409+ // stays true and the modal never reopens — leaving the connect button stuck
410+ // on "Loading…". Bumping reauthNonce (from the connect dropdown) clears that
411+ // latch and refetches the session so the session-check effect reopens the
412+ // auth modal.
413+ useEffect ( ( ) => {
414+ if ( reauthNonce > 0 ) {
415+ setHasCheckedSession ( false ) ;
416+ setCheckingSession ( false ) ;
417+ setShowAuthModal ( false ) ;
418+ void refetchWalletSession ( ) ;
419+ }
420+ } , [ reauthNonce , refetchWalletSession ] ) ;
421+
401422 const handleAuthModalAuthorized = useCallback ( async ( ) => {
402423 setShowAuthModal ( false ) ;
403424 setCheckingSession ( false ) ;
0 commit comments