File size: 6,303 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 |
"use client"
import { useState, useEffect } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Loader2, ExternalLink } from "lucide-react"
import { useWalletContext } from "@/providers/wallet-provider"
import { ethers } from "ethers"
import { CONTRACT_ADDRESSES, NETWORKS } from "@/lib/constants"
// Assuming DonationRouterABI is correctly defined and exported from this path
import { DonationRouterABI } from "@/lib/abis/DonationRouterABI"
interface Donation {
recipient: string
amount: string // Keep as string as it's formatted ethers
timestamp: number
transactionHash?: string
}
export function DonationHistory() {
const { address, isConnected, provider, chainId } = useWalletContext()
const [donations, setDonations] = useState<Donation[]>([])
const [isLoading, setIsLoading] = useState(false)
const fetchDonationHistory = async () => {
if (!isConnected || !provider || !address || !chainId) {
// Added chainId check for CONTRACT_ADDRESSES
setDonations([])
return
}
setIsLoading(true)
try {
// Ensure CONTRACT_ADDRESSES[chainId] and CONTRACT_ADDRESSES[chainId].DONATION_ROUTER exist
const routerAddress = CONTRACT_ADDRESSES[chainId]?.DONATION_ROUTER
if (!routerAddress) {
console.error(`DonationRouter contract address not found for chainId: ${chainId}`)
setDonations([]) // Or handle with mock data as before
// For demo purposes, show mock data if contract address is missing
setDonations([
{
recipient: "0xf39Fd6e51aad88F6F4ce6aB8829539c652746fF0",
amount: "0.1",
timestamp: Date.now() - 86400000,
transactionHash: "0x123...def123",
},
{
recipient: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
amount: "0.05",
timestamp: Date.now() - 172800000,
transactionHash: "0xabc...cde",
},
])
setIsLoading(false)
return
}
const donationRouter = new ethers.Contract(routerAddress, DonationRouterABI, provider)
// Get donation history from contract
// Ensure getDonationHistory method exists on the contract and returns expected structure
const history = await donationRouter.getDonationHistory(address)
// Format the donation history
const formattedHistory: Donation[] = history.map((item: any) => ({
recipient: item[0], // Assuming item[0] is address string
amount: ethers.formatEther(item[1]), // Assuming item[1] is BigNumberish
timestamp: Number(item[2]), // Assuming item[2] is BigNumberish or number
transactionHash: item[3] || undefined, // Assuming item[3] is string or undefined
}))
setDonations(formattedHistory)
} catch (error) {
console.error("Error fetching donation history:", error)
// For demo purposes, show mock data if contract call fails
setDonations([
{
recipient: "0xf39Fd6e51aad88F6F4ce6aB8829539c652746fF0",
amount: "0.1",
timestamp: Date.now() - 86400000, // 1 day ago
transactionHash: "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234",
},
{
recipient: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
amount: "0.05",
timestamp: Date.now() - 172800000, // 2 days ago
transactionHash: "0xabcdef123456789abcdef123456789abcdef123456789abcdef123456789abcde",
},
])
} finally {
setIsLoading(false)
}
}
useEffect(() => {
fetchDonationHistory()
}, [isConnected, provider, address, chainId]) // Added chainId dependency
// Get transaction explorer URL
const getExplorerUrl = (hash: string) => {
if (!hash || !chainId) return ""
const network = Object.values(NETWORKS).find((n) => n.chainId === chainId)
if (!network || !network.blockExplorer) return ""
return `${network.blockExplorer}/tx/${hash}`
}
// Format date
const formatDate = (timestamp: number) => {
return new Date(timestamp * 1000).toLocaleDateString() // Assuming timestamp is in seconds
}
return (
<Card className="border-blue-500/30 bg-black/60 backdrop-blur-xl">
<CardHeader className="pb-2">
<CardTitle className="text-blue-300">Your Donation History</CardTitle>
</CardHeader>
<CardContent>
{isLoading ? (
<div className="flex items-center justify-center py-4">
<Loader2 className="h-6 w-6 mr-2 animate-spin text-blue-400" />
<span className="text-blue-100/70">Loading donation history...</span>
</div>
) : !isConnected ? (
<div className="text-center py-4 text-blue-100/70">Connect your wallet to view donation history</div>
) : donations.length === 0 ? (
<div className="text-center py-4 text-blue-100/70">No donations found</div>
) : (
<div className="space-y-4">
{donations.map((donation, index) => (
<div key={index} className="p-3 rounded-lg border border-blue-500/20 bg-blue-950/20">
<div className="flex justify-between items-start">
<div>
<Badge className="bg-blue-600 text-white mb-2">{donation.amount} BNB</Badge>
<p className="text-sm text-blue-100/70">
To: {donation.recipient.substring(0, 6)}...
{donation.recipient.substring(donation.recipient.length - 4)}
</p>
<p className="text-xs text-blue-100/50">{formatDate(donation.timestamp)}</p>
</div>
{donation.transactionHash && (
<a
href={getExplorerUrl(donation.transactionHash)}
target="_blank"
rel="noopener noreferrer"
className="text-blue-400 hover:text-blue-300"
>
<ExternalLink className="h-4 w-4" />
</a>
)}
</div>
</div>
))}
</div>
)}
</CardContent>
</Card>
)
}
|