ln / components /flb-token-dashboard.tsx
MoShow's picture
Upload 252 files
78d0e31 verified
"use client"
import { useState } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"
import { Coins, Send, RefreshCw, ExternalLink, AlertCircle } from "lucide-react"
import { useWallet } from "@/providers/wallet-provider"
import { transferFLBTokens } from "@/lib/contract-service"
import { toast } from "@/hooks/use-toast"
import { FLB_TOKEN_ADDRESSES } from "@/lib/constants"
export function FLBTokenDashboard() {
const { connected, address, balance, chainId, signer, updateBalance } = useWallet()
const [transferTo, setTransferTo] = useState("")
const [transferAmount, setTransferAmount] = useState("")
const [transferring, setTransferring] = useState(false)
const [refreshing, setRefreshing] = useState(false)
const isOnAlfajores = chainId === 44787
const contractAddress = isOnAlfajores ? FLB_TOKEN_ADDRESSES.CELO_ALFAJORES : null
const handleTransfer = async () => {
if (!signer || !transferTo || !transferAmount) {
toast({
title: "Invalid Input",
description: "Please enter a valid address and amount",
variant: "destructive",
})
return
}
if (Number.parseFloat(transferAmount) > Number.parseFloat(balance.flb)) {
toast({
title: "Insufficient Balance",
description: "You don't have enough FLB tokens",
variant: "destructive",
})
return
}
setTransferring(true)
try {
const result = await transferFLBTokens(signer, transferTo, transferAmount)
toast({
title: "Transfer Initiated",
description: `Transaction hash: ${result.hash.slice(0, 10)}...`,
})
// Wait for transaction confirmation
await result.transaction.wait()
toast({
title: "Transfer Successful",
description: `Sent ${transferAmount} FLB to ${transferTo.slice(0, 10)}...`,
})
// Reset form and update balance
setTransferTo("")
setTransferAmount("")
await updateBalance()
} catch (error: any) {
console.error("Transfer failed:", error)
toast({
title: "Transfer Failed",
description: error.message || "Failed to transfer FLB tokens",
variant: "destructive",
})
} finally {
setTransferring(false)
}
}
const handleRefreshBalance = async () => {
setRefreshing(true)
try {
await updateBalance()
toast({
title: "Balance Updated",
description: "Your token balance has been refreshed",
})
} catch (error) {
toast({
title: "Refresh Failed",
description: "Failed to update balance",
variant: "destructive",
})
} finally {
setRefreshing(false)
}
}
const openContractOnExplorer = () => {
if (contractAddress) {
window.open(`https://alfajores.celoscan.io/address/${contractAddress}`, "_blank")
}
}
if (!connected) {
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Coins className="h-5 w-5" />
FLB Token Dashboard
</CardTitle>
<CardDescription>Connect your wallet to view and manage your FLB tokens</CardDescription>
</CardHeader>
<CardContent>
<div className="text-center py-8 text-muted-foreground">Please connect your wallet to continue</div>
</CardContent>
</Card>
)
}
return (
<div className="space-y-6">
{/* Balance Card */}
<Card>
<CardHeader>
<CardTitle className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Coins className="h-5 w-5" />
FLB Token Balance
</div>
<Button variant="outline" size="sm" onClick={handleRefreshBalance} disabled={refreshing}>
<RefreshCw className={`h-4 w-4 ${refreshing ? "animate-spin" : ""}`} />
</Button>
</CardTitle>
<CardDescription>Your current FLB token holdings on Celo Alfajores</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="text-center">
<div className="text-3xl font-bold">{Number.parseFloat(balance.flb).toFixed(4)}</div>
<div className="text-muted-foreground">FLB Tokens</div>
</div>
{!isOnAlfajores && (
<div className="flex items-center gap-2 p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
<AlertCircle className="h-4 w-4 text-yellow-600" />
<span className="text-sm text-yellow-800">
Switch to Celo Alfajores testnet to interact with FLB tokens
</span>
</div>
)}
{contractAddress && (
<div className="flex items-center justify-between text-sm">
<span className="text-muted-foreground">Contract Address:</span>
<div className="flex items-center gap-2">
<code className="bg-muted px-2 py-1 rounded text-xs">
{contractAddress.slice(0, 10)}...{contractAddress.slice(-8)}
</code>
<Button variant="ghost" size="sm" onClick={openContractOnExplorer} className="h-6 w-6 p-0">
<ExternalLink className="h-3 w-3" />
</Button>
</div>
</div>
)}
</div>
</CardContent>
</Card>
{/* Transfer Card */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Send className="h-5 w-5" />
Transfer FLB Tokens
</CardTitle>
<CardDescription>Send FLB tokens to another address</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="transfer-to">Recipient Address</Label>
<Input
id="transfer-to"
placeholder="0x..."
value={transferTo}
onChange={(e) => setTransferTo(e.target.value)}
disabled={!isOnAlfajores}
/>
</div>
<div className="space-y-2">
<Label htmlFor="transfer-amount">Amount (FLB)</Label>
<Input
id="transfer-amount"
type="number"
placeholder="0.0"
value={transferAmount}
onChange={(e) => setTransferAmount(e.target.value)}
disabled={!isOnAlfajores}
/>
<div className="text-xs text-muted-foreground">
Available: {Number.parseFloat(balance.flb).toFixed(4)} FLB
</div>
</div>
<Button
onClick={handleTransfer}
disabled={!isOnAlfajores || transferring || !transferTo || !transferAmount}
className="w-full"
>
{transferring ? "Transferring..." : "Transfer FLB"}
</Button>
</div>
</CardContent>
</Card>
{/* Network Info */}
<Card>
<CardHeader>
<CardTitle>Network Information</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
<div className="flex justify-between">
<span>Network:</span>
<Badge variant={isOnAlfajores ? "default" : "secondary"}>
{isOnAlfajores ? "Celo Alfajores" : "Other Network"}
</Badge>
</div>
<div className="flex justify-between">
<span>Chain ID:</span>
<span className="font-mono">{chainId}</span>
</div>
<div className="flex justify-between">
<span>FLB Contract:</span>
<span className="font-mono text-sm">{contractAddress ? "Deployed" : "Not Available"}</span>
</div>
</div>
</CardContent>
</Card>
</div>
)
}