Skip to content

Commit f1165fe

Browse files
Copilot0xrinegade
andcommitted
Replace all fake analytics data with real blockchain queries
Co-authored-by: 0xrinegade <[email protected]>
1 parent 303012a commit f1165fe

File tree

3 files changed

+250
-183
lines changed

3 files changed

+250
-183
lines changed

src/components/AnalyticsDashboard.js

Lines changed: 165 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
import React, { useState, useEffect, useContext } from 'react';
22
import { AppContext } from '@/contexts/AppContext';
33
import { usePhantomWallet } from '@/contexts/PhantomWalletProvider';
4+
import { useProgram } from '../hooks/useProgram';
5+
import { useProgramStatistics, useOffers, useUserHistory } from '../hooks/useOnChainData';
6+
import { useRealPriceData } from '../hooks/usePriceData';
47
import OverviewPanel from '@/components/analytics/OverviewPanel';
58
import RecentTrades from '@/components/analytics/RecentTrades';
69
import VolumePerDayChart from '@/components/analytics/VolumePerDayChart';
710
import TopTraders from '@/components/analytics/TopTraders';
811

912
export default function AnalyticsDashboard() {
1013
const { network, selectedNetwork, networks } = useContext(AppContext);
11-
const { connected, publicKey } = usePhantomWallet();
14+
const { connected, publicKey, connection } = usePhantomWallet();
1215
const [timeframe, setTimeframe] = useState('24h');
13-
const [refreshInterval, setRefreshInterval] = useState(null);
1416

15-
// Real-time protocol data states
17+
// Initialize program with connection and wallet
18+
const program = useProgram(connection, { publicKey, signTransaction: () => {} });
19+
20+
// Real blockchain data hooks
21+
const { statistics: programStats, loading: statsLoading, error: statsError } = useProgramStatistics(program);
22+
const { offers: allOffers, loading: offersLoading, error: offersError } = useOffers(program);
23+
const { prices: solPrices } = useRealPriceData();
24+
25+
// Real-time protocol data states - derived from blockchain data
1626
const [protocolOverview, setProtocolOverview] = useState({
1727
totalTrades: 0,
1828
protocolVolume: 0,
@@ -28,105 +38,91 @@ export default function AnalyticsDashboard() {
2838
const [volumeData, setVolumeData] = useState([]);
2939
const [topTradersData, setTopTradersData] = useState([]);
3040

31-
// Initialize real-time data fetching
41+
// Process real blockchain data when it becomes available
3242
useEffect(() => {
33-
// Initial data fetch
34-
fetchAllProtocolData();
35-
36-
// Set up real-time updates every 5 seconds
37-
const interval = setInterval(fetchAllProtocolData, 5000);
38-
setRefreshInterval(interval);
39-
40-
return () => {
41-
if (interval) {
42-
clearInterval(interval);
43-
}
44-
};
45-
}, [selectedNetwork, timeframe]);
46-
47-
const fetchAllProtocolData = async () => {
48-
try {
49-
// Simulate API calls to fetch real-time protocol data
50-
await Promise.all([
51-
fetchProtocolOverview(),
52-
fetchRecentTradesData(),
53-
fetchVolumeData(),
54-
fetchTopTradersData()
55-
]);
56-
} catch (error) {
57-
console.error('Error fetching protocol analytics data:', error);
43+
if (programStats && allOffers && solPrices) {
44+
const solPrice = solPrices.usd || 150; // Use USD price, fallback to 150
45+
// Calculate protocol overview from real blockchain data
46+
const overview = calculateProtocolOverview(programStats, allOffers, solPrice);
47+
setProtocolOverview(overview);
48+
49+
// Process recent trades from real offers
50+
const trades = processRecentTrades(allOffers, solPrice);
51+
setRecentTrades(trades);
52+
53+
// Generate volume data from real offers
54+
const volume = calculateVolumeData(allOffers, timeframe, solPrice);
55+
setVolumeData(volume);
56+
57+
// Calculate top traders from real reputation data
58+
const topTraders = calculateTopTraders(allOffers);
59+
setTopTradersData(topTraders);
5860
}
59-
};
61+
}, [programStats, allOffers, solPrices, timeframe]);
6062

61-
const fetchProtocolOverview = async () => {
62-
// Simulate fetching protocol overview metrics
63-
const mockData = {
64-
totalTrades: Math.floor(Math.random() * 5000) + 1000, // 1000-6000 trades
65-
protocolVolume: Math.random() * 50000 + 10000, // 10K-60K SOL
66-
totalFees: Math.random() * 50000 + 5000, // $5K-$55K in fees
67-
completionRate: 85 + (Math.random() * 10), // 85-95%
68-
tradesChange: Math.random() * 20 - 5, // -5% to +15%
69-
volumeChange: Math.random() * 30 - 10, // -10% to +20%
70-
feesChange: Math.random() * 25 - 5, // -5% to +20%
71-
completionChange: Math.random() * 5 - 2 // -2% to +3%
63+
// Calculate protocol overview from real blockchain data
64+
const calculateProtocolOverview = (stats, offers, price) => {
65+
const completedOffers = offers.filter(offer => offer.status === 'Completed');
66+
const totalVolume = completedOffers.reduce((sum, offer) => sum + offer.solAmount, 0);
67+
const totalFiatValue = totalVolume * price;
68+
const totalFees = totalFiatValue * 0.005; // 0.5% protocol fee
69+
70+
return {
71+
totalTrades: stats.offers.total,
72+
protocolVolume: totalVolume,
73+
totalFees: totalFees,
74+
completionRate: stats.offers.completionRate,
75+
tradesChange: 0, // Would need historical data to calculate
76+
volumeChange: 0, // Would need historical data to calculate
77+
feesChange: 0, // Would need historical data to calculate
78+
completionChange: 0 // Would need historical data to calculate
7279
};
73-
setProtocolOverview(mockData);
7480
};
7581

76-
const fetchRecentTradesData = async () => {
77-
// Simulate fetching recent protocol trades (last 100)
78-
const mockTrades = Array.from({ length: 100 }, (_, i) => {
79-
const tradeId = `T${Date.now().toString().slice(-6)}_${i.toString().padStart(3, '0')}`;
80-
const types = ['buy', 'sell'];
81-
const statuses = ['completed', 'in_progress', 'cancelled', 'disputed'];
82-
const currencies = ['USD', 'EUR', 'GBP'];
83-
84-
const solAmount = Math.random() * 10 + 0.1; // 0.1-10 SOL
85-
const rate = 130 + (Math.random() * 40); // $130-170 per SOL
86-
const fiatAmount = solAmount * rate;
87-
88-
return {
89-
tradeId,
90-
type: types[Math.floor(Math.random() * types.length)],
91-
status: statuses[Math.floor(Math.random() * statuses.length)],
92-
buyer: `${Math.random().toString(36).substring(2, 15)}`,
93-
seller: `${Math.random().toString(36).substring(2, 15)}`,
94-
solAmount,
95-
fiatAmount,
96-
currency: currencies[Math.floor(Math.random() * currencies.length)],
97-
rate,
98-
timestamp: new Date(Date.now() - Math.random() * 86400000 * 7), // Last 7 days
99-
completionTime: Math.random() > 0.7 ? `${Math.floor(Math.random() * 30 + 5)}min` : null,
100-
protocolFee: solAmount * 0.005 // 0.5% protocol fee
101-
};
102-
});
103-
104-
// Sort by timestamp, newest first
105-
mockTrades.sort((a, b) => b.timestamp - a.timestamp);
106-
setRecentTrades(mockTrades);
82+
// Process real offers into recent trades format
83+
const processRecentTrades = (offers, price) => {
84+
return offers
85+
.filter(offer => offer.status !== 'Created')
86+
.sort((a, b) => b.updatedAt - a.updatedAt)
87+
.slice(0, 100)
88+
.map(offer => ({
89+
tradeId: offer.id.slice(-8),
90+
type: offer.buyer ? 'sell' : 'buy',
91+
status: offer.status.toLowerCase().replace(/([A-Z])/g, '_$1').toLowerCase(),
92+
buyer: offer.buyer || 'pending',
93+
seller: offer.seller,
94+
solAmount: offer.solAmount,
95+
fiatAmount: offer.fiatAmount,
96+
currency: offer.fiatCurrency,
97+
rate: offer.fiatAmount / offer.solAmount,
98+
timestamp: new Date(offer.updatedAt),
99+
completionTime: offer.status === 'Completed' ?
100+
`${Math.floor((offer.updatedAt - offer.createdAt) / 60000)}min` : null,
101+
protocolFee: offer.solAmount * 0.005
102+
}));
107103
};
108104

109-
const fetchVolumeData = async () => {
110-
// Simulate fetching volume data based on timeframe
111-
let dataPointsCount;
112-
let timeIncrement;
105+
// Calculate volume data from real offers
106+
const calculateVolumeData = (offers, timeframe, price) => {
107+
const completedOffers = offers.filter(offer => offer.status === 'Completed');
113108

109+
let dataPointsCount, timeIncrement;
114110
switch (timeframe) {
115111
case '1h':
116-
dataPointsCount = 60; // 60 minutes
117-
timeIncrement = 60 * 1000; // 1 minute
112+
dataPointsCount = 60;
113+
timeIncrement = 60 * 1000;
118114
break;
119115
case '24h':
120-
dataPointsCount = 24; // 24 hours
121-
timeIncrement = 60 * 60 * 1000; // 1 hour
116+
dataPointsCount = 24;
117+
timeIncrement = 60 * 60 * 1000;
122118
break;
123119
case '7d':
124-
dataPointsCount = 7; // 7 days
125-
timeIncrement = 24 * 60 * 60 * 1000; // 1 day
120+
dataPointsCount = 7;
121+
timeIncrement = 24 * 60 * 60 * 1000;
126122
break;
127123
case '30d':
128-
dataPointsCount = 30; // 30 days
129-
timeIncrement = 24 * 60 * 60 * 1000; // 1 day
124+
dataPointsCount = 30;
125+
timeIncrement = 24 * 60 * 60 * 1000;
130126
break;
131127
default:
132128
dataPointsCount = 24;
@@ -135,41 +131,85 @@ export default function AnalyticsDashboard() {
135131

136132
const now = new Date();
137133
const volumePoints = Array.from({ length: dataPointsCount }, (_, i) => {
138-
const time = new Date(now.getTime() - (dataPointsCount - 1 - i) * timeIncrement);
139-
const baseVolume = 1000 + Math.random() * 5000; // Base volume
140-
const volume = baseVolume + Math.sin(i / 5) * 1000; // Add some wave pattern
134+
const timeStart = new Date(now.getTime() - (dataPointsCount - i) * timeIncrement);
135+
const timeEnd = new Date(timeStart.getTime() + timeIncrement);
136+
137+
const volumeInPeriod = completedOffers
138+
.filter(offer => {
139+
const offerTime = new Date(offer.updatedAt);
140+
return offerTime >= timeStart && offerTime < timeEnd;
141+
})
142+
.reduce((sum, offer) => sum + offer.solAmount, 0);
141143

142144
return {
143-
time: time.toISOString(),
144-
volume: Math.max(0, volume) // Ensure non-negative
145+
time: timeStart.toISOString(),
146+
volume: volumeInPeriod
145147
};
146148
});
147149

148-
setVolumeData(volumePoints);
150+
return volumePoints;
149151
};
150152

151-
const fetchTopTradersData = async () => {
152-
// Simulate fetching top 100 traders data
153-
const mockTraders = Array.from({ length: 100 }, (_, i) => {
154-
const baseAddress = Math.random().toString(36).substring(2, 15);
155-
const address = `${baseAddress}...${Math.random().toString(36).substring(2, 6)}`;
153+
// Calculate top traders from real offer data
154+
const calculateTopTraders = (offers) => {
155+
const traderStats = {};
156+
157+
offers.forEach(offer => {
158+
// Process seller stats
159+
if (!traderStats[offer.seller]) {
160+
traderStats[offer.seller] = {
161+
address: offer.seller,
162+
tradeCount: 0,
163+
volume: 0,
164+
successfulTrades: 0,
165+
disputedTrades: 0
166+
};
167+
}
156168

157-
const tradeCount = Math.floor(Math.random() * 500) + 10; // 10-510 trades
158-
const volume = Math.random() * 100000 + 1000; // 1K-101K SOL
159-
const pnl = (Math.random() - 0.3) * 50000; // -15K to +35K (bias towards positive)
160-
const successRate = 60 + Math.random() * 35; // 60-95%
169+
traderStats[offer.seller].tradeCount++;
170+
traderStats[offer.seller].volume += offer.solAmount;
161171

162-
return {
163-
address,
164-
tradeCount,
165-
volume,
166-
pnl,
167-
successRate,
168-
verified: Math.random() > 0.8 // 20% are verified
169-
};
172+
if (offer.status === 'Completed') {
173+
traderStats[offer.seller].successfulTrades++;
174+
} else if (offer.status === 'DisputeOpened') {
175+
traderStats[offer.seller].disputedTrades++;
176+
}
177+
178+
// Process buyer stats if exists
179+
if (offer.buyer && offer.buyer !== 'pending') {
180+
if (!traderStats[offer.buyer]) {
181+
traderStats[offer.buyer] = {
182+
address: offer.buyer,
183+
tradeCount: 0,
184+
volume: 0,
185+
successfulTrades: 0,
186+
disputedTrades: 0
187+
};
188+
}
189+
190+
traderStats[offer.buyer].tradeCount++;
191+
traderStats[offer.buyer].volume += offer.solAmount;
192+
193+
if (offer.status === 'Completed') {
194+
traderStats[offer.buyer].successfulTrades++;
195+
} else if (offer.status === 'DisputeOpened') {
196+
traderStats[offer.buyer].disputedTrades++;
197+
}
198+
}
170199
});
171-
172-
setTopTradersData(mockTraders);
200+
201+
// Convert to array and calculate derived metrics
202+
return Object.values(traderStats)
203+
.map(trader => ({
204+
...trader,
205+
successRate: trader.tradeCount > 0 ?
206+
(trader.successfulTrades / trader.tradeCount) * 100 : 0,
207+
pnl: 0, // Would need more complex calculation with buy/sell price differences
208+
verified: false // Would need verification system
209+
}))
210+
.filter(trader => trader.tradeCount > 0)
211+
.sort((a, b) => b.volume - a.volume)
212+
.slice(0, 100);
173213
};
174214

175215
const timeframeOptions = [
@@ -179,6 +219,10 @@ export default function AnalyticsDashboard() {
179219
{ value: '30d', label: '30D' }
180220
];
181221

222+
// Show loading state while fetching real blockchain data
223+
const isLoading = statsLoading || offersLoading;
224+
const hasError = statsError || offersError;
225+
182226
return (
183227
<div className="analytics-dashboard">
184228
<div className="analytics-header">
@@ -189,6 +233,8 @@ export default function AnalyticsDashboard() {
189233
</h1>
190234
<p className="analytics-subtitle">
191235
Monitor svmp2p trading performance and user metrics on {network.name}
236+
{isLoading && " [LOADING BLOCKCHAIN DATA...]"}
237+
{hasError && " [ERROR LOADING DATA]"}
192238
</p>
193239
</div>
194240

@@ -208,7 +254,7 @@ export default function AnalyticsDashboard() {
208254
<div className="connection-status">
209255
{connected ? (
210256
<span className="status-connected">
211-
[ONLINE] {network.name}
257+
[ONLINE] {network.name} - BLOCKCHAIN DATA
212258
</span>
213259
) : (
214260
<span className="status-disconnected">
@@ -221,26 +267,30 @@ export default function AnalyticsDashboard() {
221267
</div>
222268

223269
<div className="analytics-content">
224-
{/* Protocol Overview Panel - KPI Summary */}
270+
{/* Protocol Overview Panel - Real KPI Summary from Blockchain */}
225271
<OverviewPanel
226272
data={protocolOverview}
227273
network={network}
228274
timeframe={timeframe}
275+
loading={isLoading}
276+
error={hasError}
229277
/>
230278

231279
<div className="analytics-grid">
232280
{/* Left Column - Volume Chart and Top Traders */}
233281
<div className="analytics-column-left">
234-
{/* Volume Per Day Chart */}
282+
{/* Volume Per Day Chart - Real Blockchain Data */}
235283
<VolumePerDayChart
236284
data={volumeData}
237285
network={network}
238286
timeframe={timeframe}
287+
loading={isLoading}
239288
/>
240289

241-
{/* Top Traders Rankings */}
290+
{/* Top Traders Rankings - Real Blockchain Data */}
242291
<TopTraders
243292
tradersData={topTradersData}
293+
loading={isLoading}
244294
/>
245295
</div>
246296

@@ -249,6 +299,7 @@ export default function AnalyticsDashboard() {
249299
<RecentTrades
250300
trades={recentTrades}
251301
network={network}
302+
loading={isLoading}
252303
/>
253304
</div>
254305
</div>

0 commit comments

Comments
 (0)