diff --git a/src/components/common/cardano-objects/connect-wallet.tsx b/src/components/common/cardano-objects/connect-wallet.tsx
index 456d8752..be8c98dc 100644
--- a/src/components/common/cardano-objects/connect-wallet.tsx
+++ b/src/components/common/cardano-objects/connect-wallet.tsx
@@ -1,4 +1,4 @@
-import { Wallet, Loader2, CheckCircle2, AlertCircle } from "lucide-react";
+import { Wallet, Loader2, CheckCircle2, AlertCircle, ShieldCheck } from "lucide-react";
import { Button } from "@/components/ui/button";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import {
@@ -98,6 +98,7 @@ function ConnectWalletContent({
const { user, isLoading: isUserLoading } = useUser();
const userAddress = useUserStore((state) => state.userAddress);
const setUserAddress = useUserStore((state) => state.setUserAddress);
+ const requestReauth = useUserStore((state) => state.requestReauth);
const { toast } = useToast();
// Use WalletContext for regular wallet connection
@@ -654,6 +655,17 @@ function ConnectWalletContent({
>
);
}
+ // Connected but the user query resolved with no user → no wallet session
+ // was established (authorization failed/cancelled). Don't spin forever:
+ // show an actionable "Authorize" label; the dropdown offers re-authorize.
+ if (isConnected && !user && !isUserLoading && !isConnecting) {
+ return (
+ <>
+
+ Authorize
+ >
+ );
+ }
if (isConnected && isLoading) {
return (
<>
@@ -745,6 +757,22 @@ function ConnectWalletContent({
{isConnected && (
<>
+ {!user && !isUserLoading && (
+ requestReauth()}
+ className={cn(
+ "px-3 py-2.5 rounded-md",
+ "text-zinc-900 dark:text-zinc-50",
+ "hover:bg-zinc-100 dark:hover:bg-zinc-800",
+ "focus:bg-zinc-100 dark:focus:bg-zinc-800",
+ "transition-colors duration-150",
+ "cursor-pointer"
+ )}
+ >
+
+ Authorize wallet
+
+ )}
state.userAddress);
const setUserAddress = useUserStore((state) => state.setUserAddress);
+ const reauthNonce = useUserStore((state) => state.reauthNonce);
const ctx = api.useUtils();
// State for wallet authorization modal
@@ -257,7 +263,7 @@ export default function RootLayout({
activeWallet.getUsedAddresses()
.then((addresses) => {
if (addresses && addresses.length > 0) {
- setUserAddress(addresses[0]!);
+ setUserAddress(normalizeAddressToBech32(addresses[0]!));
fetchingAddressRef.current = false;
} else {
return activeWallet.getUnusedAddresses();
@@ -265,7 +271,7 @@ export default function RootLayout({
})
.then((addresses) => {
if (addresses && addresses.length > 0 && !userAddress) {
- setUserAddress(addresses[0]!);
+ setUserAddress(normalizeAddressToBech32(addresses[0]!));
}
fetchingAddressRef.current = false;
})
@@ -398,6 +404,21 @@ export default function RootLayout({
// Don't refetch here - let the natural query refetch handle it if needed
}, []);
+ // Manual re-authorization: when the user is connected but never got a
+ // session (e.g. the auto-authorize failed/was cancelled), hasCheckedSession
+ // stays true and the modal never reopens — leaving the connect button stuck
+ // on "Loading…". Bumping reauthNonce (from the connect dropdown) clears that
+ // latch and refetches the session so the session-check effect reopens the
+ // auth modal.
+ useEffect(() => {
+ if (reauthNonce > 0) {
+ setHasCheckedSession(false);
+ setCheckingSession(false);
+ setShowAuthModal(false);
+ void refetchWalletSession();
+ }
+ }, [reauthNonce, refetchWalletSession]);
+
const handleAuthModalAuthorized = useCallback(async () => {
setShowAuthModal(false);
setCheckingSession(false);
diff --git a/src/lib/zustand/user.ts b/src/lib/zustand/user.ts
index 076383cb..aadfe0ac 100644
--- a/src/lib/zustand/user.ts
+++ b/src/lib/zustand/user.ts
@@ -25,6 +25,11 @@ interface UserState {
setPastWallet: (pastWallet: string | undefined) => void;
pastUtxosEnabled: boolean;
setPastUtxosEnabled: (enabled: boolean | ((prev: boolean) => boolean)) => void;
+ // Bumped when the user explicitly asks to re-run wallet authorization
+ // (e.g. after a failed/cancelled auto-authorize left them connected but
+ // unauthorized). The layout watches this to reopen the auth modal.
+ reauthNonce: number;
+ requestReauth: () => void;
}
export const useUserStore = create()(
@@ -36,6 +41,8 @@ export const useUserStore = create()(
setUser: (user) => set({ user }),
pastWallet: undefined,
setPastWallet: (wallet) => set({ pastWallet: wallet }),
+ reauthNonce: 0,
+ requestReauth: () => set((state) => ({ reauthNonce: state.reauthNonce + 1 })),
pastUtxosEnabled: false,
setPastUtxosEnabled: (enabled) => {
const newValue = typeof enabled === "function" ? enabled(get().pastUtxosEnabled) : enabled;