discourse/frontend/hooks/use-trust-data.ts

138 lines
4.7 KiB
TypeScript
Raw Permalink Normal View History

2025-03-25 03:52:30 -04:00
import { useState, useEffect } from 'react';
import { ethers } from 'ethers';
import { useWalletStore } from '@/lib/wallet-store';
import { USER_TRUST_CONTRACT_ADDRESS, USER_TRUST_CONTRACT_ABI } from '@/lib/constants';
export function useTrustData() {
const { walletConnected, walletAddress, isVerified, trustScore: storeTrustScore, dailyLimit: storeDailyLimit, updateTrustScore, updateDailyLimit } = useWalletStore();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
// Trust-earning actions mapping
const trustActions = [
{ action: "Submit an unflagged perspective", points: 1 },
{ action: "Receive an upvote from a verified user", points: 5 },
{ action: "Have your perspective included in a consensus", points: 10 },
{ action: "Consistent participation (30 days)", points: 15 },
{ action: "Have zero flagged content", points: 5 }
];
// Fetch trust data from API or blockchain
const fetchTrustData = async () => {
if (!walletConnected || !walletAddress) return;
setIsLoading(true);
setError(null);
try {
// Try to get data from our API first (which may use blockchain in production)
const response = await fetch(`/api/trust?address=${walletAddress}`);
if (!response.ok) {
throw new Error('API request failed');
}
const data = await response.json();
// Update local state with data from API
updateTrustScore(data.trustScore);
updateDailyLimit(data.dailyLimit);
setLastUpdated(new Date(data.lastUpdated));
} catch (err) {
console.error('Error fetching trust data:', err);
// Fallback to blockchain directly if API fails
try {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(
window.ethereum as ethers.providers.ExternalProvider
);
const contract = new ethers.Contract(
USER_TRUST_CONTRACT_ADDRESS,
USER_TRUST_CONTRACT_ABI,
provider
);
const userData = await contract.getUserTrustData(walletAddress);
// Update local state with data from blockchain
updateTrustScore(userData.trustScore.toNumber());
updateDailyLimit(userData.dailyLimit.toNumber());
setLastUpdated(new Date());
} else {
// Just use the store values if no API and no wallet
setError('Failed to fetch trust data');
}
} catch (fallbackErr) {
console.error('Fallback error:', fallbackErr);
setError('Failed to fetch trust data from blockchain');
}
} finally {
setIsLoading(false);
}
};
// Update trust score via API
const updateUserTrust = async (action: string, amount: number = 1) => {
if (!walletConnected || !walletAddress) return;
setIsLoading(true);
setError(null);
try {
const response = await fetch('/api/trust', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
walletAddress,
action,
amount,
}),
});
if (!response.ok) {
throw new Error('API request failed');
}
const data = await response.json();
// Update local state with data from API
updateTrustScore(data.trustScore);
updateDailyLimit(data.dailyLimit);
setLastUpdated(new Date(data.lastUpdated));
return data;
} catch (err) {
console.error('Error updating trust score:', err);
setError('Failed to update trust score');
throw err;
} finally {
setIsLoading(false);
}
};
// Initial fetch on component mount
useEffect(() => {
if (walletConnected && walletAddress) {
fetchTrustData();
}
}, [walletConnected, walletAddress]);
return {
isVerified,
trustScore: storeTrustScore,
dailyLimit: storeDailyLimit,
isLoading,
error,
lastUpdated,
fetchTrustData,
updateUserTrust,
trustActions
};
}