solana / src /components /ui /wallet-button.tsx
dronesplace's picture
Initial upload
2acde71 verified
Raw
History Blame Contribute Delete
4.37 kB
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>
);
};