Spaces:
Running
Running
| import React, { useCallback } from 'react'; | |
| import { useWallet } from '@solana/wallet-adapter-react'; | |
| import { WalletMultiButton, WalletDisconnectButton } from '@solana/wallet-adapter-react-ui'; | |
| import { Button } from '@/components/ui/button'; | |
| import { Wallet, Power, AlertCircle, ExternalLink } from 'lucide-react'; | |
| import { cn } from '@/lib/utils'; | |
| import { useToast } from '@/hooks/use-toast'; | |
| import { useWalletDetection } from '@/hooks/useWalletDetection'; | |
| interface WalletButtonProps { | |
| variant?: "default" | "hero" | "outline"; | |
| className?: string; | |
| } | |
| export const WalletButton: React.FC<WalletButtonProps> = ({ | |
| variant = "default", | |
| className | |
| }) => { | |
| const { connected, disconnect, publicKey, connecting, wallet, connect } = useWallet(); | |
| const { toast } = useToast(); | |
| const { isPhantomInstalled, isWalletReady } = useWalletDetection(); | |
| const handleDirectPhantomConnect = useCallback(async () => { | |
| if (typeof window === 'undefined') return; | |
| try { | |
| const windowAny = window as any; | |
| const phantom = windowAny.phantom?.solana || windowAny.solana; | |
| if (phantom?.isPhantom) { | |
| console.log('Attempting direct Phantom connection...'); | |
| const response = await phantom.connect(); | |
| console.log('Direct connection response:', response); | |
| toast({ | |
| title: "Wallet Connected", | |
| description: "Successfully connected to Phantom wallet", | |
| }); | |
| } else { | |
| throw new Error('Phantom not found'); | |
| } | |
| } catch (error) { | |
| console.error('Direct connection failed:', error); | |
| toast({ | |
| title: "Connection Failed", | |
| description: "Please make sure Phantom is installed and unlocked", | |
| variant: "destructive", | |
| }); | |
| } | |
| }, [toast]); | |
| if (connected && publicKey) { | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| <div className="text-sm"> | |
| <div className="text-foreground font-medium"> | |
| {publicKey.toBase58().slice(0, 4)}...{publicKey.toBase58().slice(-4)} | |
| </div> | |
| <div className="text-muted-foreground text-xs">Connected</div> | |
| </div> | |
| <Button | |
| onClick={disconnect} | |
| variant="outline" | |
| size="sm" | |
| className={cn("gap-2", className)} | |
| > | |
| <Power className="h-4 w-4" /> | |
| Disconnect | |
| </Button> | |
| </div> | |
| ); | |
| } | |
| // Show install prompt if Phantom is not detected | |
| if (!isPhantomInstalled) { | |
| return ( | |
| <div className={cn("flex items-center gap-2", className)}> | |
| <Button | |
| onClick={() => window.open('https://phantom.app/', '_blank')} | |
| variant="outline" | |
| className="gap-2" | |
| > | |
| <ExternalLink className="h-4 w-4" /> | |
| Install Phantom | |
| </Button> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className={cn("flex items-center gap-2", className)}> | |
| {/* Standard wallet adapter button */} | |
| <div className="wallet-adapter-button-trigger"> | |
| <WalletMultiButton | |
| className={cn( | |
| "!rounded-md !text-sm !font-medium !transition-all !duration-300", | |
| "!ring-offset-background !focus-visible:outline-none !focus-visible:ring-2 !focus-visible:ring-ring !focus-visible:ring-offset-2", | |
| "!disabled:pointer-events-none !disabled:opacity-50", | |
| "!hover:scale-105 !active:scale-95", | |
| variant === "hero" && "!bg-gradient-primary !text-primary-foreground !shadow-lg !hover:opacity-90", | |
| variant === "outline" && "!border !border-input !bg-background !text-foreground !hover:bg-accent !hover:text-accent-foreground", | |
| variant === "default" && "!bg-primary !text-primary-foreground !hover:bg-primary/90", | |
| connecting && "!opacity-75 !cursor-wait" | |
| )} | |
| startIcon={<Wallet className="h-4 w-4" />} | |
| /> | |
| </div> | |
| {/* Fallback direct connection button */} | |
| {!connected && !connecting && ( | |
| <Button | |
| onClick={handleDirectPhantomConnect} | |
| variant="ghost" | |
| size="sm" | |
| className="gap-2 text-xs" | |
| > | |
| <AlertCircle className="h-3 w-3" /> | |
| Direct Connect | |
| </Button> | |
| )} | |
| </div> | |
| ); | |
| }; |