File size: 5,905 Bytes
78d0e31 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
"use client"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Wallet, Copy, ExternalLink, LogOut, Coins, AlertCircle } from "lucide-react"
import { useWallet } from "@/providers/wallet-provider"
import { NetworkSwitcher } from "./network-switcher"
import { toast } from "@/hooks/use-toast"
export function ConnectWalletButton() {
const { connected, address, balance, chainId, isConnecting, error, connectWallet, disconnect, requestFLBTokens } =
useWallet()
const [requesting, setRequesting] = useState(false)
const handleConnect = async () => {
try {
const success = await connectWallet()
if (success) {
toast({
title: "Wallet Connected",
description: "Successfully connected to your Celo wallet",
})
}
} catch (error) {
toast({
title: "Connection Failed",
description: "Failed to connect wallet. Please try again.",
variant: "destructive",
})
}
}
const handleDisconnect = () => {
disconnect()
toast({
title: "Wallet Disconnected",
description: "Your wallet has been disconnected",
})
}
const handleCopyAddress = () => {
if (address) {
navigator.clipboard.writeText(address)
toast({
title: "Address Copied",
description: "Wallet address copied to clipboard",
})
}
}
const handleRequestTokens = async () => {
setRequesting(true)
try {
await requestFLBTokens("100")
toast({
title: "Tokens Requested",
description: "FLB tokens have been requested. Please check your balance.",
})
} catch (error: any) {
toast({
title: "Request Failed",
description: error.message || "Failed to request FLB tokens. Please contact the team.",
variant: "destructive",
})
} finally {
setRequesting(false)
}
}
const openBlockExplorer = () => {
if (address) {
const explorerUrl =
chainId === 42220
? `https://celoscan.io/address/${address}`
: `https://alfajores.celoscan.io/address/${address}`
window.open(explorerUrl, "_blank")
}
}
const formatAddress = (addr: string) => {
return `${addr.slice(0, 6)}...${addr.slice(-4)}`
}
const formatBalance = (bal: string) => {
const num = Number.parseFloat(bal)
return num > 0 ? num.toFixed(4) : "0"
}
const isCeloNetwork = chainId === 42220 || chainId === 44787
if (!connected) {
return (
<div className="space-y-2">
<Button onClick={handleConnect} disabled={isConnecting} className="gap-2 w-full" size="lg">
<Wallet className="h-4 w-4" />
{isConnecting ? "Connecting..." : "Connect Wallet"}
</Button>
{error && (
<div className="text-sm text-red-400 bg-red-950/30 p-2 rounded border border-red-500/30 flex items-center gap-2">
<AlertCircle className="h-4 w-4 flex-shrink-0" />
<span>{error}</span>
</div>
)}
</div>
)
}
return (
<div className="flex items-center gap-2">
<NetworkSwitcher />
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="gap-2 bg-transparent">
<Wallet className="h-4 w-4" />
<div className="flex flex-col items-start">
<span className="text-sm font-medium">{address ? formatAddress(address) : "Connected"}</span>
<div className="flex gap-2 text-xs text-muted-foreground">
<span>{formatBalance(balance.celo)} CELO</span>
<span>•</span>
<span>{formatBalance(balance.flb)} FLB</span>
</div>
</div>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-64">
<div className="p-2">
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium">Wallet Address</span>
<Button variant="ghost" size="sm" onClick={handleCopyAddress} className="h-6 w-6 p-0">
<Copy className="h-3 w-3" />
</Button>
</div>
<code className="text-xs bg-muted p-2 rounded block break-all">{address}</code>
</div>
<DropdownMenuSeparator />
<div className="p-2">
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-sm">CELO Balance:</span>
<Badge variant="outline">{formatBalance(balance.celo)} CELO</Badge>
</div>
<div className="flex justify-between">
<span className="text-sm">FLB Balance:</span>
<Badge variant="outline">{formatBalance(balance.flb)} FLB</Badge>
</div>
</div>
</div>
<DropdownMenuSeparator />
{isCeloNetwork && (
<DropdownMenuItem onClick={handleRequestTokens} disabled={requesting}>
<Coins className="h-4 w-4 mr-2" />
{requesting ? "Requesting..." : "Request Test FLB"}
</DropdownMenuItem>
)}
<DropdownMenuItem onClick={openBlockExplorer}>
<ExternalLink className="h-4 w-4 mr-2" />
View on Explorer
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={handleDisconnect} className="text-red-600">
<LogOut className="h-4 w-4 mr-2" />
Disconnect
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
)
}
|