SC CODE: Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "dashboard-blocks.js")
31 STORE("descrHdr", "Latest block info module")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "explorer.tela")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "2671bad697aaf40cb4f5903abb37f22fb08e47e8e59695836644e5a379140550")
37 STORE("fileCheckS", "df528c9bf0218b384df4150f5833caa007f3d04b787bee25fc759b23ccfda65")
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-blocks',
version:'1.0.0',
// Block monitoring variables
lastKnownHeight: 0,
monitoringEnabled: true,
async renderBlocksModule() {
return `
<!-- Latest Block Info -->
<div class="enhanced-card">
<div class="card-header">
<h2 style="color: #fff; font-size: 1.6rem; font-weight: 700; margin: 0;">Latest Block Info</h2>
<div class="actions">
<button onclick="window.dashboardBlocks.toggleMonitoring()" id="blocks-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 blockchain height and block details • <span id="blocks-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(180px, 1fr)); gap: 1rem;" id="latest-block-info">
<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;">Latest Block</div>
<div style="color: #b959b6; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="latest-block-height">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="latest-block-time">—</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;">Block Hash</div>
<div style="color: #52c8db; font-size: 1.1rem; font-weight: 600; font-family: monospace; word-break: break-all;" id="latest-block-hash">Loading...</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;">Timestamp</div>
<div style="color: #fbbf24; font-size: 1.3rem; font-weight: 700; margin-bottom: 0.5rem;" id="latest-block-timestamp">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="latest-block-relative">—</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;">Block Reward</div>
<div style="color: #b959b6; font-size: 1.5rem; font-weight: 700;" id="latest-block-reward">Loading...</div>
</div>
</div>
</div>
</div>`;
},
async updateModule() {
if(!this.monitoringEnabled) return;
// Check if we're on dashboard page and if required elements exist
if(window.r !== 'home' && window.r !== '' && window.r) return;
try {
const blockHeader = await window.xswd.getLastBlockHeader();
if(!blockHeader) return;
const blockCount = await window.xswd.getBlockCount();
// Extract actual block data from response
const blockData = blockHeader.block_header || blockHeader;
// Update block info
const height = blockData.height || 0;
const hash = blockData.hash || '';
const timestamp = blockData.timestamp || 0;
const reward = blockData.reward || 0;
// Update display elements - check if they exist first
const heightEl = document.getElementById('latest-block-height');
if(heightEl) heightEl.textContent = height.toLocaleString();
const hashEl = document.getElementById('latest-block-hash');
if(hashEl) {
hashEl.innerHTML = this.formatHashResponsive(hash, `#block/${height}`);
if(window.checkHashDisplay) window.checkHashDisplay();
}
const timestampEl = document.getElementById('latest-block-timestamp');
if(timestampEl) timestampEl.textContent = this.formatTimestamp(timestamp);
const relativeEl = document.getElementById('latest-block-relative');
if(relativeEl) relativeEl.textContent = this.formatRelativeTime(timestamp);
const rewardEl = document.getElementById('latest-block-reward');
if(rewardEl) rewardEl.textContent = this.formatReward(reward);
// Check for new blocks
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
const timeStr = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', second:'2-digit'});
if(height > this.lastKnownHeight && this.lastKnownHeight > 0) {
statusEl.textContent = `NEW BLOCK at ${timeStr}`;
statusEl.style.color = '#fbbf24';
setTimeout(() => {
statusEl.textContent = 'Live';
statusEl.style.color = '#4ade80';
}, 3000);
} else {
statusEl.textContent = `Updated ${timeStr}`;
statusEl.style.color = '#4ade80';
}
}
this.lastKnownHeight = height;
} catch(error) {
console.error('Block module update failed:', error);
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Block Error';
statusEl.style.color = '#ef4444';
}
}
},
formatHash(hash) {
if(!hash) return 'Unknown';
return hash.length > 16 ? hash.substring(0, 8) + '...' + hash.substring(hash.length - 8) : hash;
},
formatHashResponsive(hash, linkHref) {
if (!hash || hash.length < 16) return 'Unknown';
const fullHash = hash;
const truncatedHash = hash.substring(0, 8) + '...' + hash.substring(hash.length - 8);
const linkStart = linkHref ? `<a href="${linkHref}" style="color:#52c8db;text-decoration:none;" onmouseover="this.style.textDecoration='underline'" onmouseout="this.style.textDecoration='none'">` : '';
const linkEnd = linkHref ? '</a>' : '';
return `<span class="hash-container hash-responsive">
<span class="hash-full">${linkStart}${fullHash}${linkEnd}</span>
<span class="hash-truncated">${linkStart}${truncatedHash}${linkEnd}</span>
</span>`;
},
formatTimestamp(timestamp) {
if(!timestamp) return 'Unknown';
// Handle different timestamp formats from DERO API
let date;
if(timestamp > 1000000000000) {
// Already in milliseconds
date = new Date(timestamp);
} else if(timestamp > 1000000000) {
// Unix timestamp in seconds
date = new Date(timestamp * 1000);
} else {
// Use current time if timestamp seems invalid
date = new Date();
}
return date.toLocaleString();
},
formatRelativeTime(timestamp) {
if(!timestamp) return '—';
// Convert timestamp to milliseconds if needed
let timestampMs;
if(timestamp > 1000000000000) {
timestampMs = timestamp;
} else if(timestamp > 1000000000) {
timestampMs = timestamp * 1000;
} else {
return 'Just now';
}
const now = Date.now();
const diff = (now - timestampMs) / 1000; // difference in seconds
if(diff < 60) return 'Just now';
if(diff < 3600) return Math.floor(diff / 60) + 'm ago';
if(diff < 86400) return Math.floor(diff / 3600) + 'h ago';
return Math.floor(diff / 86400) + 'd ago';
},
formatReward(reward) {
if(!reward) return '0 DERO';
return (reward / 100000).toFixed(5) + ' DERO';
},
toggleMonitoring() {
this.monitoringEnabled = !this.monitoringEnabled;
const btn = document.getElementById('blocks-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 statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Stopped';
statusEl.style.color = '#888';
}
}
}
return this.monitoringEnabled;
},
stopMonitoring() {
this.monitoringEnabled = false;
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Stopped';
statusEl.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-blocks.js")
31 STORE("descrHdr", "Latest block info module")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "explorer.tela")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "2671bad697aaf40cb4f5903abb37f22fb08e47e8e59695836644e5a379140550")
37 STORE("fileCheckS", "df528c9bf0218b384df4150f5833caa007f3d04b787bee25fc759b23ccfda65")
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-blocks',
version:'1.0.0',
// Block monitoring variables
lastKnownHeight: 0,
monitoringEnabled: true,
async renderBlocksModule() {
return `
<!-- Latest Block Info -->
<div class="enhanced-card">
<div class="card-header">
<h2 style="color: #fff; font-size: 1.6rem; font-weight: 700; margin: 0;">Latest Block Info</h2>
<div class="actions">
<button onclick="window.dashboardBlocks.toggleMonitoring()" id="blocks-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 blockchain height and block details • <span id="blocks-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(180px, 1fr)); gap: 1rem;" id="latest-block-info">
<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;">Latest Block</div>
<div style="color: #b959b6; font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem;" id="latest-block-height">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="latest-block-time">—</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;">Block Hash</div>
<div style="color: #52c8db; font-size: 1.1rem; font-weight: 600; font-family: monospace; word-break: break-all;" id="latest-block-hash">Loading...</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;">Timestamp</div>
<div style="color: #fbbf24; font-size: 1.3rem; font-weight: 700; margin-bottom: 0.5rem;" id="latest-block-timestamp">Loading...</div>
<div style="color: #888; font-size: 0.8rem;" id="latest-block-relative">—</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;">Block Reward</div>
<div style="color: #b959b6; font-size: 1.5rem; font-weight: 700;" id="latest-block-reward">Loading...</div>
</div>
</div>
</div>
</div>`;
},
async updateModule() {
if(!this.monitoringEnabled) return;
// Check if we're on dashboard page and if required elements exist
if(window.r !== 'home' && window.r !== '' && window.r) return;
try {
const blockHeader = await window.xswd.getLastBlockHeader();
if(!blockHeader) return;
const blockCount = await window.xswd.getBlockCount();
// Extract actual block data from response
const blockData = blockHeader.block_header || blockHeader;
// Update block info
const height = blockData.height || 0;
const hash = blockData.hash || '';
const timestamp = blockData.timestamp || 0;
const reward = blockData.reward || 0;
// Update display elements - check if they exist first
const heightEl = document.getElementById('latest-block-height');
if(heightEl) heightEl.textContent = height.toLocaleString();
const hashEl = document.getElementById('latest-block-hash');
if(hashEl) {
hashEl.innerHTML = this.formatHashResponsive(hash, `#block/${height}`);
if(window.checkHashDisplay) window.checkHashDisplay();
}
const timestampEl = document.getElementById('latest-block-timestamp');
if(timestampEl) timestampEl.textContent = this.formatTimestamp(timestamp);
const relativeEl = document.getElementById('latest-block-relative');
if(relativeEl) relativeEl.textContent = this.formatRelativeTime(timestamp);
const rewardEl = document.getElementById('latest-block-reward');
if(rewardEl) rewardEl.textContent = this.formatReward(reward);
// Check for new blocks
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
const timeStr = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit', second:'2-digit'});
if(height > this.lastKnownHeight && this.lastKnownHeight > 0) {
statusEl.textContent = `NEW BLOCK at ${timeStr}`;
statusEl.style.color = '#fbbf24';
setTimeout(() => {
statusEl.textContent = 'Live';
statusEl.style.color = '#4ade80';
}, 3000);
} else {
statusEl.textContent = `Updated ${timeStr}`;
statusEl.style.color = '#4ade80';
}
}
this.lastKnownHeight = height;
} catch(error) {
console.error('Block module update failed:', error);
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Block Error';
statusEl.style.color = '#ef4444';
}
}
},
formatHash(hash) {
if(!hash) return 'Unknown';
return hash.length > 16 ? hash.substring(0, 8) + '...' + hash.substring(hash.length - 8) : hash;
},
formatHashResponsive(hash, linkHref) {
if (!hash || hash.length < 16) return 'Unknown';
const fullHash = hash;
const truncatedHash = hash.substring(0, 8) + '...' + hash.substring(hash.length - 8);
const linkStart = linkHref ? `<a href="${linkHref}" style="color:#52c8db;text-decoration:none;" onmouseover="this.style.textDecoration='underline'" onmouseout="this.style.textDecoration='none'">` : '';
const linkEnd = linkHref ? '</a>' : '';
return `<span class="hash-container hash-responsive">
<span class="hash-full">${linkStart}${fullHash}${linkEnd}</span>
<span class="hash-truncated">${linkStart}${truncatedHash}${linkEnd}</span>
</span>`;
},
formatTimestamp(timestamp) {
if(!timestamp) return 'Unknown';
// Handle different timestamp formats from DERO API
let date;
if(timestamp > 1000000000000) {
// Already in milliseconds
date = new Date(timestamp);
} else if(timestamp > 1000000000) {
// Unix timestamp in seconds
date = new Date(timestamp * 1000);
} else {
// Use current time if timestamp seems invalid
date = new Date();
}
return date.toLocaleString();
},
formatRelativeTime(timestamp) {
if(!timestamp) return '—';
// Convert timestamp to milliseconds if needed
let timestampMs;
if(timestamp > 1000000000000) {
timestampMs = timestamp;
} else if(timestamp > 1000000000) {
timestampMs = timestamp * 1000;
} else {
return 'Just now';
}
const now = Date.now();
const diff = (now - timestampMs) / 1000; // difference in seconds
if(diff < 60) return 'Just now';
if(diff < 3600) return Math.floor(diff / 60) + 'm ago';
if(diff < 86400) return Math.floor(diff / 3600) + 'h ago';
return Math.floor(diff / 86400) + 'd ago';
},
formatReward(reward) {
if(!reward) return '0 DERO';
return (reward / 100000).toFixed(5) + ' DERO';
},
toggleMonitoring() {
this.monitoringEnabled = !this.monitoringEnabled;
const btn = document.getElementById('blocks-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 statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Stopped';
statusEl.style.color = '#888';
}
}
}
return this.monitoringEnabled;
},
stopMonitoring() {
this.monitoringEnabled = false;
const statusEl = document.getElementById('blocks-last-updated');
if(statusEl) {
statusEl.textContent = 'Stopped';
statusEl.style.color = '#888';
}
}
})
*/'] |