Copy class PortfolioManager {
constructor(apiKey, userAddress) {
this.client = new IllumindClient({ apiKey });
this.userAddress = userAddress;
this.portfolio = {
totalValue: 0,
todaysPnL: 0,
accuracy: 0,
activePositions: [],
historicalPerformance: []
};
}
async updatePortfolio() {
try {
const [userStats, predictions, currentRound] = await Promise.all([
this.client.stats.getUser(this.userAddress),
this.client.predictions.getUser(this.userAddress, { status: 'active' }),
this.client.rounds.getCurrent()
]);
this.portfolio = {
totalValue: parseFloat(ethers.utils.formatEther(userStats.totalRewards)),
netProfit: parseFloat(ethers.utils.formatEther(userStats.netProfit)),
accuracy: userStats.accuracy,
currentStreak: userStats.currentStreak,
totalPredictions: userStats.totalPredictions,
activePositions: this.calculateActivePositions(predictions.predictions, currentRound),
rank: userStats.rank
};
this.emitPortfolioUpdate();
} catch (error) {
console.error('Portfolio update failed:', error);
}
}
calculateActivePositions(predictions, currentRound) {
return predictions.map(pred => {
const timeRemaining = Math.max(0, currentRound.endTime - Date.now()) / 1000;
const currentPrice = currentRound.currentPrice || currentRound.priceAtStart;
const priceChange = currentPrice - currentRound.priceAtStart;
const isWinning = (pred.direction === 'UP' && priceChange > 0) ||
(pred.direction === 'DOWN' && priceChange < 0);
return {
predictionId: pred.predictionId,
roundId: pred.roundId,
direction: pred.direction,
amount: parseFloat(ethers.utils.formatEther(pred.amount)),
timeRemaining,
isWinning,
estimatedReward: parseFloat(ethers.utils.formatEther(pred.expectedReward)),
currentPnL: isWinning ?
parseFloat(ethers.utils.formatEther(pred.expectedReward)) - parseFloat(ethers.utils.formatEther(pred.amount)) :
-parseFloat(ethers.utils.formatEther(pred.amount))
};
});
}
async getPerformanceAnalytics() {
const predictions = await this.client.predictions.getUser(this.userAddress, {
status: 'all',
limit: 1000
});
return {
dailyAccuracy: this.calculateDailyAccuracy(predictions.predictions),
bestTimeframes: this.findBestPerformingTimeframes(predictions.predictions),
directionBias: this.analyzeDirectionBias(predictions.predictions),
stakingStrategy: this.analyzeStakingPatterns(predictions.predictions)
};
}
calculateDailyAccuracy(predictions) {
const dailyStats = new Map();
predictions.forEach(pred => {
const date = new Date(pred.timestamp).toDateString();
if (!dailyStats.has(date)) {
dailyStats.set(date, { total: 0, successful: 0 });
}
const stats = dailyStats.get(date);
stats.total++;
if (pred.status === 'won') {
stats.successful++;
}
});
return Array.from(dailyStats.entries()).map(([date, stats]) => ({
date,
accuracy: (stats.successful / stats.total) * 100,
totalPredictions: stats.total
}));
}
// Subscribe to real-time updates
startRealTimeTracking() {
this.client.ws.subscribe('rounds', (data) => {
// Update active positions with real-time data
this.updateActivePositionsRealTime(data);
});
// Update portfolio every 30 seconds
setInterval(() => {
this.updatePortfolio();
}, 30000);
}
emitPortfolioUpdate() {
// Emit event for UI updates
this.emit('portfolioUpdate', this.portfolio);
}
}