@@ -64,6 +64,7 @@ export default function EditProfilePage() {
6464 const [ ownershipChecked , setOwnershipChecked ] = useState ( false ) ;
6565 const [ submitting , setSubmitting ] = useState ( false ) ;
6666 const [ authError , setAuthError ] = useState < string | null > ( null ) ;
67+ const [ walletPrompt , setWalletPrompt ] = useState < "locked" | "not-owner" | null > ( null ) ;
6768 const [ fieldErrors , setFieldErrors ] = useState < FieldErrors > ( { } ) ;
6869
6970 const [ form , setForm ] = useState ( {
@@ -81,6 +82,8 @@ export default function EditProfilePage() {
8182 const [ assetError , setAssetError ] = useState < string | null > ( null ) ;
8283
8384 useEffect ( ( ) => {
85+ if ( ownershipChecked ) return ;
86+
8487 async function init ( ) {
8588 try {
8689 const res = await fetch ( `${ API_BASE_URL } /profiles/${ username } ` ) ;
@@ -93,8 +96,14 @@ export default function EditProfilePage() {
9396 const result = await getAddress ( ) . catch ( ( ) => ( { address : "" , error : "Freighter not available" } ) ) ;
9497 const connectedAddress = "address" in result ? result . address : "" ;
9598
96- if ( ! connectedAddress || connectedAddress !== profile . walletAddress ) {
97- router . replace ( `/profile/${ username } ` ) ;
99+ if ( ! connectedAddress ) {
100+ // Wallet not connected or Freighter is locked — show a prompt instead of silently redirecting
101+ setWalletPrompt ( "locked" ) ;
102+ return ;
103+ }
104+
105+ if ( connectedAddress !== profile . walletAddress ) {
106+ setWalletPrompt ( "not-owner" ) ;
98107 return ;
99108 }
100109
@@ -120,7 +129,7 @@ export default function EditProfilePage() {
120129 }
121130 }
122131 init ( ) ;
123- } , [ username , router ] ) ;
132+ } , [ username , router , ownershipChecked ] ) ;
124133
125134 function setField ( field : keyof typeof form ) {
126135 return ( e : React . ChangeEvent < HTMLInputElement | HTMLTextAreaElement > ) => {
@@ -209,6 +218,55 @@ export default function EditProfilePage() {
209218 ) ;
210219 }
211220
221+ if ( walletPrompt === "locked" ) {
222+ return (
223+ < AppShell >
224+ < div className = "flex h-[60vh] flex-col items-center justify-center gap-4 text-center px-4" >
225+ < div className = "rounded-full bg-yellow-500/10 p-4 text-3xl" > 🔒</ div >
226+ < h2 className = "text-xl font-bold text-white" > Connect your wallet to edit this profile</ h2 >
227+ < p className = "text-sm text-steel max-w-sm" >
228+ Freighter is not connected or is locked. Unlock your Freighter wallet and try again.
229+ </ p >
230+ < button
231+ type = "button"
232+ onClick = { ( ) => {
233+ setLoading ( true ) ;
234+ setWalletPrompt ( null ) ;
235+ // Re-run the init flow by resetting ownershipChecked
236+ setOwnershipChecked ( false ) ;
237+ } }
238+ className = "min-h-[44px] rounded-xl bg-mint px-6 text-sm font-bold text-ink hover:bg-mint/90 transition-colors"
239+ >
240+ Try again
241+ </ button >
242+ < Link href = { `/profile/${ username } ` } className = "text-sm text-steel hover:text-white transition-colors" >
243+ ← Back to profile
244+ </ Link >
245+ </ div >
246+ </ AppShell >
247+ ) ;
248+ }
249+
250+ if ( walletPrompt === "not-owner" ) {
251+ return (
252+ < AppShell >
253+ < div className = "flex h-[60vh] flex-col items-center justify-center gap-4 text-center px-4" >
254+ < div className = "rounded-full bg-red-500/10 p-4 text-3xl" > 🚫</ div >
255+ < h2 className = "text-xl font-bold text-white" > Access denied</ h2 >
256+ < p className = "text-sm text-steel max-w-sm" >
257+ The connected wallet does not match this profile. Switch to the correct wallet in Freighter and try again.
258+ </ p >
259+ < Link
260+ href = { `/profile/${ username } ` }
261+ className = "min-h-[44px] inline-flex items-center rounded-xl bg-white/10 px-6 text-sm font-bold text-white hover:bg-white/20 transition-colors"
262+ >
263+ ← Back to profile
264+ </ Link >
265+ </ div >
266+ </ AppShell >
267+ ) ;
268+ }
269+
212270 if ( authError ) {
213271 return (
214272 < AppShell >
0 commit comments