Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions src/app/authentication/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// / 3. Updated Authentication component
"use client";

import React, { useState } from "react";
import { WalletModal } from "@/components/WalletModal";
import { Button } from "@/components/ui/button";
import { Wallet } from "lucide-react";
import { Wallet, CheckCircle } from "lucide-react";
import { useWalletContext } from "@/context/WalletContext";

export default function Authentication() {
const [isModalOpen, setIsModalOpen] = useState(false);
const { isConnected, address, connectorName } = useWalletContext();

return (
<section id="authentication" className="relative min-h-screen">
Expand All @@ -19,24 +22,48 @@ export default function Authentication() {
<div className="flex flex-col items-center text-center space-y-4 max-w-3xl mx-auto">
<h1 className="text-4xl md:text-6xl font-bold tracking-tight">
<span className="block bg-gradient-to-r from-indigo-400 via-purple-500 to-pink-500 bg-clip-text text-transparent">
Connect Your Wallet
{isConnected ? "Wallet Connected" : "Connect Your Wallet"}
</span>
</h1>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
Securely log in using your Starknet wallet for a privacy-focused experience.
{isConnected
? `Successfully connected with ${connectorName}`
: "Securely log in using your Starknet wallet for a privacy-focused experience."
}
</p>
</div>

{/* Wallet Connect Button */}
<div className="flex justify-center">
<Button
size="lg"
className="bg-gradient-to-r from-indigo-500 to-purple-700 hover:from-indigo-600 hover:to-purple-800"
onClick={() => setIsModalOpen(true)}
>
<Wallet className="mr-2 h-5 w-5" />
Connect Wallet
</Button>
{isConnected ? (
<div className="flex flex-col items-center space-y-4">
<div className="flex items-center space-x-2 text-green-600">
<CheckCircle className="h-5 w-5" />
<span className="font-medium">Wallet Connected</span>
</div>
<p className="text-sm text-muted-foreground break-all max-w-md">
{address}
</p>
<Button
size="lg"
variant="outline"
onClick={() => setIsModalOpen(true)}
>
<Wallet className="mr-2 h-5 w-5" />
Manage Wallet
</Button>
</div>
) : (
<Button
size="lg"
className="bg-gradient-to-r from-indigo-500 to-purple-700 hover:from-indigo-600 hover:to-purple-800"
onClick={() => setIsModalOpen(true)}
>
<Wallet className="mr-2 h-5 w-5" />
Connect Wallet
</Button>
)}

<WalletModal
isOpen={isModalOpen}
onOpenChange={setIsModalOpen}
Expand All @@ -55,4 +82,4 @@ export default function Authentication() {
</div>
</section>
);
}
}
18 changes: 14 additions & 4 deletions src/components/StarknetProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
// providers/StarknetProvider.tsx
"use client";

import { StarknetConfig, publicProvider } from "@starknet-react/core";
import { sepolia } from "@starknet-react/chains";
import { WalletProvider } from "@/context/WalletContext";
import { WalletLoader } from "@/components/WalletLoader";
import { WalletErrorBoundary } from "@/components/WalletErrorBoundary";

export default function StarknetProvider({ children }: { children: React.ReactNode }) {
return (
<StarknetConfig chains={[sepolia]} provider={publicProvider()}>
{children}
</StarknetConfig>
<WalletErrorBoundary>
<StarknetConfig chains={[sepolia]} provider={publicProvider()}>
<WalletProvider>
<WalletLoader>
{children}
</WalletLoader>
</WalletProvider>
</StarknetConfig>
</WalletErrorBoundary>
);
}
}
119 changes: 119 additions & 0 deletions src/components/WalletErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// components/WalletErrorBoundary.tsx
"use client";

import React from 'react';
import { Button } from '@/components/ui/button';

interface WalletErrorBoundaryState {
hasError: boolean;
error?: Error;
}

interface WalletErrorBoundaryProps {
children: React.ReactNode;
}

class WalletErrorBoundary extends React.Component<
WalletErrorBoundaryProps,
WalletErrorBoundaryState
> {
constructor(props: WalletErrorBoundaryProps) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error: Error): WalletErrorBoundaryState {
// Check if it's a wallet-related error
const isWalletError =
error.message?.includes('toLowerCase') ||
error.message?.includes('WalletAccount') ||
error.message?.includes('Account') ||
error.stack?.includes('starknet');

return {
hasError: !!isWalletError,
error: isWalletError ? error : undefined,
};
}

componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
// Only log wallet-related errors
if (this.state.hasError) {
console.error('Wallet Error:', error);
console.error('Error Info:', errorInfo);

// Clear any potentially corrupted wallet data
try {
localStorage.removeItem('wallet_connection');
} catch (e) {
console.error('Failed to clear wallet connection:', e);
}
}
}

handleRetry = () => {
// Clear the error state and try to reload
this.setState({ hasError: false, error: undefined });

// Clear localStorage wallet data
try {
localStorage.removeItem('wallet_connection');
} catch (e) {
console.error('Failed to clear wallet connection:', e);
}

// Optionally reload the page for a fresh start
window.location.reload();
};

render() {
if (this.state.hasError) {
return (
<div className="min-h-screen flex items-center justify-center bg-background">
<div className="text-center space-y-6 max-w-md mx-auto p-6">
<div className="text-6xl">⚠️</div>
<h2 className="text-2xl font-bold text-red-600">
Wallet Connection Error
</h2>
<p className="text-muted-foreground">
There was an issue connecting to your wallet. This might be due to:
</p>
<ul className="text-sm text-muted-foreground text-left space-y-1">
<li>• Wallet extension not properly installed</li>
<li>• Network connectivity issues</li>
<li>• Corrupted wallet data</li>
<li>• Browser compatibility issues</li>
</ul>
<div className="space-y-3">
<Button
onClick={this.handleRetry}
className="w-full bg-gradient-to-r from-indigo-500 to-purple-700 hover:from-indigo-600 hover:to-purple-800"
>
Clear Data & Retry
</Button>
<p className="text-xs text-muted-foreground">
This will clear your wallet connection data and refresh the page
</p>
</div>
{process.env.NODE_ENV === 'development' && this.state.error && (
<details className="text-left">
<summary className="text-sm text-muted-foreground cursor-pointer">
Show error details (Development)
</summary>
<pre className="text-xs bg-gray-100 dark:bg-gray-800 p-2 rounded mt-2 overflow-auto">
{this.state.error.message}
{'\n\n'}
{this.state.error.stack}
</pre>
</details>
)}
</div>
</div>
);
}

return this.props.children;
}
}

export { WalletErrorBoundary };
67 changes: 67 additions & 0 deletions src/components/WalletLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// components/WalletLoader.tsx
"use client";

import React, { useEffect, useState } from 'react';
import { useWalletContext } from '@/context/WalletContext';
import { useAccount } from '@starknet-react/core';

interface WalletLoaderProps {
children: React.ReactNode;
}

const WalletLoader = ({ children }: WalletLoaderProps) => {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const { restoreConnection } = useWalletContext();
useAccount();

useEffect(() => {
const initializeWallet = async () => {
try {
setError(null);
await restoreConnection();
} catch (error: unknown) {
console.error('Failed to restore wallet connection:', error);
if (error && typeof error === 'object' && 'message' in error && typeof (error as { message?: unknown }).message === 'string') {
setError((error as { message: string }).message);
} else {
setError('Failed to initialize wallet connection');
}

// Clear potentially corrupted data
try {
localStorage.removeItem('wallet_connection');
} catch (e) {
console.error('Failed to clear wallet connection:', e);
}
} finally {
// Give a small delay to ensure everything is initialized
setTimeout(() => {
setIsLoading(false);
}, 500);
}
};

initializeWallet();
}, [restoreConnection]);

if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center bg-background">
<div className="text-center space-y-4">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-600 mx-auto"></div>
<p className="text-muted-foreground">Initializing wallet connection...</p>
{error && (
<p className="text-red-500 text-sm max-w-md">
{error}
</p>
)}
</div>
</div>
);
}

return <>{children}</>;
};

export { WalletLoader };
Loading
Loading