Following the Stellar/Soroban example dapp pattern:
export function useFreighter() {
const [account, setAccount] = useState<FreighterAccount | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// Check if Freighter is installed
const isFreighterInstalled = () => {
return typeof window !== 'undefined' && !!window.freighterApi;
};
// Connect to Freighter
const connect = async () => {
const publicKey = await window.freighterApi!.getPublicKey();
setAccount({
address: publicKey,
displayName: `${publicKey.slice(0, 4)}...${publicKey.slice(-4)}`,
});
setIsConnected(true);
};
// ... disconnect, signTransaction
}Key Features:
- ✅ Proper state management
- ✅ Error handling
- ✅ Loading states
- ✅ Installation detection
- ✅ Transaction signing support
Inspired by Cometswap's clean, modern design:
<WalletConnect />Features:
- Connected State: Shows wallet address with dropdown menu
- Disconnected State: Shows connect button with gradient
- Dropdown Menu:
- Copy address
- View on Stellar Expert
- Disconnect option
- Animations: Framer Motion for smooth transitions
- Loading States: Spinner during connection
- Error Display: Shows connection errors
Design Elements:
- Gradient buttons (purple to pink)
- Backdrop blur effects
- Shadow effects
- Smooth animations
- Modern dropdown with dark theme
Full Radix UI dropdown menu implementation:
- DropdownMenu
- DropdownMenuTrigger
- DropdownMenuContent
- DropdownMenuItem
- DropdownMenuLabel
- DropdownMenuSeparator
- And more...
/* Gradients */
from-purple-600 to-pink-600
from-purple-600/20 to-pink-600/20
/* Borders */
border-purple-500/50
hover:border-purple-400
/* Shadows */
shadow-lg shadow-purple-500/50
/* Backdrop */
backdrop-blur-sm- Card-based Layout: Clean cards with borders and shadows
- Gradient Accents: Purple/pink gradients for CTAs
- Backdrop Blur: Frosted glass effect
- Smooth Animations: Framer Motion throughout
- Modern Typography: Clean, readable fonts
// ❌ Simple button with alert
<Button onClick={connectWallet}>
Connect Freighter Wallet
</Button>
// ❌ Manual state management
const [walletAddress, setWalletAddress] = useState<string | null>(null);
// ❌ No error handling
// ❌ No loading states
// ❌ No dropdown menu// ✅ Professional wallet component
<WalletConnect />
// ✅ Custom hook with full state management
const { account, isConnected, connect, disconnect } = useFreighter();
// ✅ Error handling
// ✅ Loading states
// ✅ Dropdown menu with actions
// ✅ Smooth animationsimport { WalletConnect } from '@/components/WalletConnect';
import { useFreighter } from '@/hooks/useFreighter';
export default function MyPage() {
const { account, isConnected } = useFreighter();
return (
<div>
<WalletConnect />
{isConnected && account && (
<div>
<p>Connected: {account.address}</p>
{/* Your app logic */}
</div>
)}
</div>
);
}const {
account, // { address: string, displayName: string } | null
isConnected, // boolean
isLoading, // boolean
error, // string | null
isFreighterInstalled, // boolean
connect, // () => Promise<boolean>
disconnect, // () => void
signTransaction, // (xdr: string, networkPassphrase: string) => Promise<string>
} = useFreighter();Disconnected State:
- Gradient button (purple → pink)
- "Connect Wallet" or "Install Freighter"
- Loading spinner during connection
- Error message display
Connected State:
- Shows truncated address
- Gradient background with blur
- Wallet icon
- Dropdown trigger
Menu Items:
- My Wallet (label)
- Address (click to copy)
- View on Explorer (opens Stellar Expert)
- Disconnect (red text)
Styling:
- Dark theme (gray-900 background)
- Hover effects
- Icons for each action
- Smooth animations
// Primary Gradient
bg-gradient-to-r from-purple-600 to-pink-600
// Accent Gradient (subtle)
from-purple-600/20 to-pink-600/20
// Borders
border-purple-500/50
border-gray-700
// Text
text-white
text-gray-400
text-red-400 (disconnect)
// Backgrounds
bg-gray-900
bg-gray-800 (hover)// Blur
backdrop-blur-sm
// Shadows
shadow-lg shadow-purple-500/50
// Animations
animate-spin (loading)
transition-colors (hover)// Wallet Address
font-mono text-xs
// Labels
text-sm font-semibold
// Buttons
font-semiboldOld Code (in app/page.tsx):
const [walletAddress, setWalletAddress] = useState<string | null>(null);
const connectWallet = async () => {
try {
await connectFreighter();
const pk = await getPublicKey();
setWalletAddress(pk);
} catch (error) {
// ...
}
};
<Button onClick={connectWallet}>Connect Freighter Wallet</Button>New Code:
import { WalletConnect } from '@/components/WalletConnect';
import { useFreighter } from '@/hooks/useFreighter';
const { account, isConnected } = useFreighter();
<WalletConnect />
{isConnected && account && (
// Your connected UI
)}- Professional wallet connection flow
- Clear loading and error states
- Easy disconnect option
- Copy address functionality
- View on explorer link
- Reusable hook
- Separation of concerns
- Type-safe
- Easy to test
- Follows React best practices
- Modern, clean aesthetic
- Matches Cometswap style
- Consistent with shadcn/ui
- Smooth animations
- Professional appearance
- Single source of truth for wallet state
- Easy to add features
- Clear component hierarchy
- Well-documented
- ✅
hooks/useFreighter.ts- Wallet hook - ✅
components/WalletConnect.tsx- Wallet UI component - ✅
components/ui/dropdown-menu.tsx- Dropdown component
- ✅
@radix-ui/react-dropdown-menu- Dropdown menu primitives
-
Update
app/page.tsx:import { WalletConnect } from '@/components/WalletConnect'; import { useFreighter } from '@/hooks/useFreighter'; // Replace old wallet connection code with: const { account, isConnected, signTransaction } = useFreighter();
-
Replace Connect Button:
// Old: <Button onClick={connectWallet}>Connect Freighter Wallet</Button> // New: <WalletConnect />
-
Update Wallet Address References:
// Old: {walletAddress && ...} // New: {isConnected && account && ...} {account?.address} // instead of walletAddress
-
Use signTransaction for Blend Operations:
const signedXdr = await signTransaction(xdr, NETWORK.passphrase);
The wallet integration now follows:
- ✅ Stellar/Soroban best practices
- ✅ Cometswap design patterns
- ✅ Modern React patterns
- ✅ Professional UX standards
The wallet connection is now production-ready with a beautiful, modern interface! 🎨
Test it at http://localhost:3000