SC CODE: Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "dashboard-network.js")
31 STORE("descrHdr", "Network health monitor module")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "explorer.tela")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "1eb4b35fa704131b5e0bc7c68e49276c4d53713a53aeee47bea8a0e169e8a443")
37 STORE("fileCheckS", "2579091198f81f69f035c946256b23e1c8b801addfceeae95e0883cfbc414da5")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*
({
name:'dashboard-network',
version:'1.0.0',
// Network health monitoring variables
lastKnownDifficulty: 0,
lastKnownHashrate: 0,
lastKnownPeerCount: 0,
lastKnownNetworkStats: {},
networkActivity: [],
monitoringEnabled: true,
async renderNetworkModule() {
return `
<!-- Network Health Monitor -->
<div class="enhanced-card">
<div class="card-header">
<h2 style="color: #fff; font-size: 1.6rem; font-weight: 700; margin: 0;">Network Health Monitor</h2>
<div class="actions">
<button onclick="window.dashboardNetwork.toggleMonitoring()" id="network-toggle-btn" style="background: rgba(74,222,128,0.1); border: 1px solid #4ade80; color: #4ade80; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; font-size: 0.8rem; font-weight: 500;">● LIVE</button>
</div>
</div>
<div class="card-content">
<div class="section-info" style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 1.5rem;">Real-time network performance and health metrics • <span id="network-last-updated" style="color: #4ade80; font-weight: 500;">Live</span></div>
<div class="stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem;" id="network-health-monitor">
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(185,89,182,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Difficulty</div>
<div style="color: #b959b6; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-difficulty">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-difficulty-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Hashrate</div>
<div style="color: #52c8db; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-hashrate">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-hashrate-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Peers</div>
<div style="color: #4ade80; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-peers">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-peers-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Health</div>
<div style="color: #4ade80; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="health-status">Monitoring...</div>
</div>
</div>
<!-- Network Activity Feed -->
<div style="margin-top: 2rem;">
<h3 style="color: #52c8db; margin-bottom: 1rem; font-size: 1.2rem; font-weight: 600;">Recent Network Activity</h3>
<div style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; max-height: 250px; overflow-y: auto;" id="network-activity-feed">
<div style="color: #b3b3b3; text-align: center; padding: 2rem; font-style: italic;">Monitoring network health...</div>
</div>
</div>
</div>
</div>`;
},
async updateModule() {
if(!this.monitoringEnabled) return;
// Check if we're on dashboard page
if(window.r !== 'home' && window.r !== '' && window.r) return;
try {
const networkInfo = await window.getCachedData('networkInfo', () => window.xswd.getNetworkInfo());
if(networkInfo) {
const currentDifficulty = networkInfo.difficulty || 0;
const currentHashrate = networkInfo.hashrate || 0;
const currentPeerCount = (networkInfo.incoming_connections_count || 0) + (networkInfo.outgoing_connections_count || 0);
// Detect changes
const networkChanges = this.detectNetworkChanges(currentDifficulty, currentHashrate, currentPeerCount);
// Update display elements
const difficultyEl = document.getElementById('network-health-difficulty');
const hashrateEl = document.getElementById('network-health-hashrate');
const peersEl = document.getElementById('network-health-peers');
if(difficultyEl) difficultyEl.textContent = this.formatDifficulty(currentDifficulty);
if(hashrateEl) hashrateEl.textContent = this.formatHashrate(currentHashrate);
if(peersEl) peersEl.textContent = currentPeerCount;
// Update change indicators
this.updateChangeIndicator('network-health-difficulty-change', networkChanges.difficultyChange);
this.updateChangeIndicator('network-health-hashrate-change', networkChanges.hashrateChange);
this.updateChangeIndicator('network-health-peers-change', networkChanges.peerChange);
// Update network health status
const healthStatus = this.calculateNetworkHealth(networkInfo);
const healthEl = document.getElementById('network-health');
const healthStatusEl = document.getElementById('health-status');
if(healthEl) healthEl.textContent = healthStatus.status;
if(healthStatusEl) healthStatusEl.textContent = healthStatus.description;
// Update status and activity feed
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
const timeStr = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', second:'2-digit'});
let hasActivity = false;
// Add network changes to activity feed
if(networkChanges.difficultyChange.hasChange) {
this.addNetworkActivity('difficulty', `Difficulty ${networkChanges.difficultyChange.direction} to ${this.formatDifficulty(currentDifficulty)} (${networkChanges.difficultyChange.percentageText})`, timeStr);
hasActivity = true;
}
if(networkChanges.hashrateChange.hasChange) {
this.addNetworkActivity('hashrate', `Hashrate ${networkChanges.hashrateChange.direction} to ${this.formatHashrate(currentHashrate)} (${networkChanges.hashrateChange.percentageText})`, timeStr);
hasActivity = true;
}
if(networkChanges.peerChange.hasChange) {
const peerChangeText = networkChanges.peerChange.delta > 0 ?
`${networkChanges.peerChange.delta} peer${networkChanges.peerChange.delta > 1 ? 's' : ''} connected` :
`${Math.abs(networkChanges.peerChange.delta)} peer${Math.abs(networkChanges.peerChange.delta) > 1 ? 's' : ''} disconnected`;
this.addNetworkActivity('peers', peerChangeText, timeStr);
hasActivity = true;
}
if(hasActivity) {
networkStatusEl.textContent = `NETWORK ACTIVITY at ${timeStr}`;
networkStatusEl.style.color = '#fbbf24';
setTimeout(() => {
networkStatusEl.textContent = 'Live';
networkStatusEl.style.color = '#4ade80';
}, 5000);
} else {
networkStatusEl.textContent = `Updated ${timeStr}`;
networkStatusEl.style.color = '#4ade80';
}
}
// Store current data for next comparison
this.lastKnownDifficulty = currentDifficulty;
this.lastKnownHashrate = currentHashrate;
this.lastKnownPeerCount = currentPeerCount;
this.lastKnownNetworkStats = networkInfo;
}
} catch(error) {
console.error('Network module update failed:', error);
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Network Error';
networkStatusEl.style.color = '#ef4444';
}
}
},
detectNetworkChanges(currentDifficulty, currentHashrate, currentPeerCount) {
const difficultyChange = this.calculatePercentageChange(this.lastKnownDifficulty, currentDifficulty, 0.01);
const hashrateChange = this.calculatePercentageChange(this.lastKnownHashrate, currentHashrate, 0.05);
const peerChange = {
hasChange: this.lastKnownPeerCount > 0 && currentPeerCount !== this.lastKnownPeerCount,
delta: currentPeerCount - this.lastKnownPeerCount,
direction: currentPeerCount > this.lastKnownPeerCount ? 'increased' : 'decreased'
};
return {
difficultyChange: difficultyChange,
hashrateChange: hashrateChange,
peerChange: peerChange
};
},
calculatePercentageChange(oldValue, newValue, threshold) {
if(!oldValue || oldValue === 0) {
return { hasChange: false, percentage: 0, direction: 'stable', percentageText: '—' };
}
const percentage = ((newValue - oldValue) / oldValue) * 100;
const hasChange = Math.abs(percentage) >= threshold;
let direction = 'stable';
let percentageText = '—';
if(hasChange) {
direction = percentage > 0 ? 'increased' : 'decreased';
const sign = percentage > 0 ? '+' : '';
percentageText = `${sign}${percentage.toFixed(2)}%`;
}
return {
hasChange: hasChange,
percentage: percentage,
direction: direction,
percentageText: percentageText
};
},
formatDifficulty(difficulty) {
if(!difficulty || difficulty === 0) return '0';
if(difficulty >= 1e9) return (difficulty / 1e9).toFixed(1) + 'G';
if(difficulty >= 1e6) return (difficulty / 1e6).toFixed(1) + 'M';
if(difficulty >= 1e3) return (difficulty / 1e3).toFixed(1) + 'K';
return difficulty.toLocaleString();
},
formatHashrate(hashrate) {
if(!hashrate || hashrate === 0) return '0 H/s';
if(hashrate >= 1e9) return (hashrate / 1e9).toFixed(1) + ' GH/s';
if(hashrate >= 1e6) return (hashrate / 1e6).toFixed(1) + ' MH/s';
if(hashrate >= 1e3) return (hashrate / 1e3).toFixed(1) + ' KH/s';
return hashrate.toFixed(0) + ' H/s';
},
updateChangeIndicator(elementId, changeData) {
const element = document.getElementById(elementId);
if(!element) return;
if(changeData.hasChange) {
element.textContent = changeData.percentageText;
if(changeData.direction === 'increased') {
element.style.color = '#4ade80';
} else if(changeData.direction === 'decreased') {
element.style.color = '#ef4444';
}
} else {
element.textContent = 'Stable';
element.style.color = '#888';
}
},
calculateNetworkHealth(networkInfo) {
let healthScore = 100;
let issues = [];
const totalPeers = (networkInfo.incoming_connections_count || 0) + (networkInfo.outgoing_connections_count || 0);
if(totalPeers < 5) {
healthScore -= 30;
issues.push('Low peer count');
} else if(totalPeers < 15) {
healthScore -= 10;
issues.push('Few peers');
}
if(!networkInfo.difficulty || !networkInfo.height) {
healthScore -= 50;
issues.push('Network data missing');
}
let status = 'Excellent';
let description = 'All systems healthy';
if(healthScore >= 90) {
status = 'Excellent';
description = 'All systems healthy';
} else if(healthScore >= 70) {
status = 'Good';
description = issues.length > 0 ? issues[0] : 'Minor issues detected';
} else if(healthScore >= 50) {
status = 'Fair';
description = issues.length > 0 ? issues.join(', ') : 'Some issues detected';
} else {
status = 'Poor';
description = 'Multiple issues detected';
}
return { status: status, description: description, score: healthScore };
},
addNetworkActivity(type, message, timestamp) {
const activity = {
type: type,
message: message,
timestamp: timestamp,
time: Date.now()
};
this.networkActivity.unshift(activity);
if(this.networkActivity.length > 10) {
this.networkActivity = this.networkActivity.slice(0, 10);
}
this.updateNetworkActivityFeed();
},
updateNetworkActivityFeed() {
const feedEl = document.getElementById('network-activity-feed');
if(!feedEl) return;
if(this.networkActivity.length === 0) {
feedEl.innerHTML = '<div style="color:#666;text-align:center;padding:2rem">No recent network activity</div>';
return;
}
const activityHtml = this.networkActivity.map(activity => {
let icon = '🌐';
if(activity.type === 'difficulty') {
icon = '⚡';
} else if(activity.type === 'hashrate') {
icon = '⛏️';
} else if(activity.type === 'peers') {
icon = '🔗';
}
return `<div style="display:flex;align-items:center;justify-content:space-between;padding:0.5rem 0;border-bottom:1px solid rgba(255,255,255,0.05)">
<div style="display:flex;align-items:center;gap:0.75rem">
<span style="font-size:1.1rem">${icon}</span>
<span style="color:#fff;font-size:0.9rem">${activity.message}</span>
</div>
<span style="color:#888;font-size:0.8rem">${activity.timestamp}</span>
</div>`;
}).join('');
feedEl.innerHTML = activityHtml;
},
toggleMonitoring() {
this.monitoringEnabled = !this.monitoringEnabled;
const btn = document.getElementById('network-toggle-btn');
if(btn) {
if(this.monitoringEnabled) {
btn.textContent = '● LIVE';
btn.style.color = '#4ade80';
btn.style.borderColor = '#4ade80';
this.updateModule();
} else {
btn.textContent = '○ STOPPED';
btn.style.color = '#888';
btn.style.borderColor = '#555';
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Stopped';
networkStatusEl.style.color = '#888';
}
}
}
return this.monitoringEnabled;
},
stopMonitoring() {
this.monitoringEnabled = false;
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Stopped';
networkStatusEl.style.color = '#888';
}
}
})
*/ |
SC Arguments: [Name:SC_ACTION Type:uint64 Value:'1' Name:SC_CODE Type:string Value:'Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "dashboard-network.js")
31 STORE("descrHdr", "Network health monitor module")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "explorer.tela")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "1eb4b35fa704131b5e0bc7c68e49276c4d53713a53aeee47bea8a0e169e8a443")
37 STORE("fileCheckS", "2579091198f81f69f035c946256b23e1c8b801addfceeae95e0883cfbc414da5")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*
({
name:'dashboard-network',
version:'1.0.0',
// Network health monitoring variables
lastKnownDifficulty: 0,
lastKnownHashrate: 0,
lastKnownPeerCount: 0,
lastKnownNetworkStats: {},
networkActivity: [],
monitoringEnabled: true,
async renderNetworkModule() {
return `
<!-- Network Health Monitor -->
<div class="enhanced-card">
<div class="card-header">
<h2 style="color: #fff; font-size: 1.6rem; font-weight: 700; margin: 0;">Network Health Monitor</h2>
<div class="actions">
<button onclick="window.dashboardNetwork.toggleMonitoring()" id="network-toggle-btn" style="background: rgba(74,222,128,0.1); border: 1px solid #4ade80; color: #4ade80; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; font-size: 0.8rem; font-weight: 500;">● LIVE</button>
</div>
</div>
<div class="card-content">
<div class="section-info" style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 1.5rem;">Real-time network performance and health metrics • <span id="network-last-updated" style="color: #4ade80; font-weight: 500;">Live</span></div>
<div class="stats-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem;" id="network-health-monitor">
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(185,89,182,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Difficulty</div>
<div style="color: #b959b6; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-difficulty">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-difficulty-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Hashrate</div>
<div style="color: #52c8db; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-hashrate">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-hashrate-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Peers</div>
<div style="color: #4ade80; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health-peers">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="network-health-peers-change">—</div>
</div>
<div class="enhanced-stat-card" style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; text-align: center; transition: all 0.2s ease;">
<div style="color: #b3b3b3; font-size: 0.9rem; margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px;">Health</div>
<div style="color: #4ade80; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="network-health">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="health-status">Monitoring...</div>
</div>
</div>
<!-- Network Activity Feed -->
<div style="margin-top: 2rem;">
<h3 style="color: #52c8db; margin-bottom: 1rem; font-size: 1.2rem; font-weight: 600;">Recent Network Activity</h3>
<div style="background: rgba(0,0,0,0.2); border: 1px solid rgba(82,200,219,0.3); border-radius: 8px; padding: 1.5rem; max-height: 250px; overflow-y: auto;" id="network-activity-feed">
<div style="color: #b3b3b3; text-align: center; padding: 2rem; font-style: italic;">Monitoring network health...</div>
</div>
</div>
</div>
</div>`;
},
async updateModule() {
if(!this.monitoringEnabled) return;
// Check if we're on dashboard page
if(window.r !== 'home' && window.r !== '' && window.r) return;
try {
const networkInfo = await window.getCachedData('networkInfo', () => window.xswd.getNetworkInfo());
if(networkInfo) {
const currentDifficulty = networkInfo.difficulty || 0;
const currentHashrate = networkInfo.hashrate || 0;
const currentPeerCount = (networkInfo.incoming_connections_count || 0) + (networkInfo.outgoing_connections_count || 0);
// Detect changes
const networkChanges = this.detectNetworkChanges(currentDifficulty, currentHashrate, currentPeerCount);
// Update display elements
const difficultyEl = document.getElementById('network-health-difficulty');
const hashrateEl = document.getElementById('network-health-hashrate');
const peersEl = document.getElementById('network-health-peers');
if(difficultyEl) difficultyEl.textContent = this.formatDifficulty(currentDifficulty);
if(hashrateEl) hashrateEl.textContent = this.formatHashrate(currentHashrate);
if(peersEl) peersEl.textContent = currentPeerCount;
// Update change indicators
this.updateChangeIndicator('network-health-difficulty-change', networkChanges.difficultyChange);
this.updateChangeIndicator('network-health-hashrate-change', networkChanges.hashrateChange);
this.updateChangeIndicator('network-health-peers-change', networkChanges.peerChange);
// Update network health status
const healthStatus = this.calculateNetworkHealth(networkInfo);
const healthEl = document.getElementById('network-health');
const healthStatusEl = document.getElementById('health-status');
if(healthEl) healthEl.textContent = healthStatus.status;
if(healthStatusEl) healthStatusEl.textContent = healthStatus.description;
// Update status and activity feed
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
const timeStr = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', second:'2-digit'});
let hasActivity = false;
// Add network changes to activity feed
if(networkChanges.difficultyChange.hasChange) {
this.addNetworkActivity('difficulty', `Difficulty ${networkChanges.difficultyChange.direction} to ${this.formatDifficulty(currentDifficulty)} (${networkChanges.difficultyChange.percentageText})`, timeStr);
hasActivity = true;
}
if(networkChanges.hashrateChange.hasChange) {
this.addNetworkActivity('hashrate', `Hashrate ${networkChanges.hashrateChange.direction} to ${this.formatHashrate(currentHashrate)} (${networkChanges.hashrateChange.percentageText})`, timeStr);
hasActivity = true;
}
if(networkChanges.peerChange.hasChange) {
const peerChangeText = networkChanges.peerChange.delta > 0 ?
`${networkChanges.peerChange.delta} peer${networkChanges.peerChange.delta > 1 ? 's' : ''} connected` :
`${Math.abs(networkChanges.peerChange.delta)} peer${Math.abs(networkChanges.peerChange.delta) > 1 ? 's' : ''} disconnected`;
this.addNetworkActivity('peers', peerChangeText, timeStr);
hasActivity = true;
}
if(hasActivity) {
networkStatusEl.textContent = `NETWORK ACTIVITY at ${timeStr}`;
networkStatusEl.style.color = '#fbbf24';
setTimeout(() => {
networkStatusEl.textContent = 'Live';
networkStatusEl.style.color = '#4ade80';
}, 5000);
} else {
networkStatusEl.textContent = `Updated ${timeStr}`;
networkStatusEl.style.color = '#4ade80';
}
}
// Store current data for next comparison
this.lastKnownDifficulty = currentDifficulty;
this.lastKnownHashrate = currentHashrate;
this.lastKnownPeerCount = currentPeerCount;
this.lastKnownNetworkStats = networkInfo;
}
} catch(error) {
console.error('Network module update failed:', error);
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Network Error';
networkStatusEl.style.color = '#ef4444';
}
}
},
detectNetworkChanges(currentDifficulty, currentHashrate, currentPeerCount) {
const difficultyChange = this.calculatePercentageChange(this.lastKnownDifficulty, currentDifficulty, 0.01);
const hashrateChange = this.calculatePercentageChange(this.lastKnownHashrate, currentHashrate, 0.05);
const peerChange = {
hasChange: this.lastKnownPeerCount > 0 && currentPeerCount !== this.lastKnownPeerCount,
delta: currentPeerCount - this.lastKnownPeerCount,
direction: currentPeerCount > this.lastKnownPeerCount ? 'increased' : 'decreased'
};
return {
difficultyChange: difficultyChange,
hashrateChange: hashrateChange,
peerChange: peerChange
};
},
calculatePercentageChange(oldValue, newValue, threshold) {
if(!oldValue || oldValue === 0) {
return { hasChange: false, percentage: 0, direction: 'stable', percentageText: '—' };
}
const percentage = ((newValue - oldValue) / oldValue) * 100;
const hasChange = Math.abs(percentage) >= threshold;
let direction = 'stable';
let percentageText = '—';
if(hasChange) {
direction = percentage > 0 ? 'increased' : 'decreased';
const sign = percentage > 0 ? '+' : '';
percentageText = `${sign}${percentage.toFixed(2)}%`;
}
return {
hasChange: hasChange,
percentage: percentage,
direction: direction,
percentageText: percentageText
};
},
formatDifficulty(difficulty) {
if(!difficulty || difficulty === 0) return '0';
if(difficulty >= 1e9) return (difficulty / 1e9).toFixed(1) + 'G';
if(difficulty >= 1e6) return (difficulty / 1e6).toFixed(1) + 'M';
if(difficulty >= 1e3) return (difficulty / 1e3).toFixed(1) + 'K';
return difficulty.toLocaleString();
},
formatHashrate(hashrate) {
if(!hashrate || hashrate === 0) return '0 H/s';
if(hashrate >= 1e9) return (hashrate / 1e9).toFixed(1) + ' GH/s';
if(hashrate >= 1e6) return (hashrate / 1e6).toFixed(1) + ' MH/s';
if(hashrate >= 1e3) return (hashrate / 1e3).toFixed(1) + ' KH/s';
return hashrate.toFixed(0) + ' H/s';
},
updateChangeIndicator(elementId, changeData) {
const element = document.getElementById(elementId);
if(!element) return;
if(changeData.hasChange) {
element.textContent = changeData.percentageText;
if(changeData.direction === 'increased') {
element.style.color = '#4ade80';
} else if(changeData.direction === 'decreased') {
element.style.color = '#ef4444';
}
} else {
element.textContent = 'Stable';
element.style.color = '#888';
}
},
calculateNetworkHealth(networkInfo) {
let healthScore = 100;
let issues = [];
const totalPeers = (networkInfo.incoming_connections_count || 0) + (networkInfo.outgoing_connections_count || 0);
if(totalPeers < 5) {
healthScore -= 30;
issues.push('Low peer count');
} else if(totalPeers < 15) {
healthScore -= 10;
issues.push('Few peers');
}
if(!networkInfo.difficulty || !networkInfo.height) {
healthScore -= 50;
issues.push('Network data missing');
}
let status = 'Excellent';
let description = 'All systems healthy';
if(healthScore >= 90) {
status = 'Excellent';
description = 'All systems healthy';
} else if(healthScore >= 70) {
status = 'Good';
description = issues.length > 0 ? issues[0] : 'Minor issues detected';
} else if(healthScore >= 50) {
status = 'Fair';
description = issues.length > 0 ? issues.join(', ') : 'Some issues detected';
} else {
status = 'Poor';
description = 'Multiple issues detected';
}
return { status: status, description: description, score: healthScore };
},
addNetworkActivity(type, message, timestamp) {
const activity = {
type: type,
message: message,
timestamp: timestamp,
time: Date.now()
};
this.networkActivity.unshift(activity);
if(this.networkActivity.length > 10) {
this.networkActivity = this.networkActivity.slice(0, 10);
}
this.updateNetworkActivityFeed();
},
updateNetworkActivityFeed() {
const feedEl = document.getElementById('network-activity-feed');
if(!feedEl) return;
if(this.networkActivity.length === 0) {
feedEl.innerHTML = '<div style="color:#666;text-align:center;padding:2rem">No recent network activity</div>';
return;
}
const activityHtml = this.networkActivity.map(activity => {
let icon = '🌐';
if(activity.type === 'difficulty') {
icon = '⚡';
} else if(activity.type === 'hashrate') {
icon = '⛏️';
} else if(activity.type === 'peers') {
icon = '🔗';
}
return `<div style="display:flex;align-items:center;justify-content:space-between;padding:0.5rem 0;border-bottom:1px solid rgba(255,255,255,0.05)">
<div style="display:flex;align-items:center;gap:0.75rem">
<span style="font-size:1.1rem">${icon}</span>
<span style="color:#fff;font-size:0.9rem">${activity.message}</span>
</div>
<span style="color:#888;font-size:0.8rem">${activity.timestamp}</span>
</div>`;
}).join('');
feedEl.innerHTML = activityHtml;
},
toggleMonitoring() {
this.monitoringEnabled = !this.monitoringEnabled;
const btn = document.getElementById('network-toggle-btn');
if(btn) {
if(this.monitoringEnabled) {
btn.textContent = '● LIVE';
btn.style.color = '#4ade80';
btn.style.borderColor = '#4ade80';
this.updateModule();
} else {
btn.textContent = '○ STOPPED';
btn.style.color = '#888';
btn.style.borderColor = '#555';
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Stopped';
networkStatusEl.style.color = '#888';
}
}
}
return this.monitoringEnabled;
},
stopMonitoring() {
this.monitoringEnabled = false;
const networkStatusEl = document.getElementById('network-last-updated');
if(networkStatusEl) {
networkStatusEl.textContent = 'Stopped';
networkStatusEl.style.color = '#888';
}
}
})
*/'] |