<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
.hivehub-grid{
margin-top:50px;
display:grid;
grid-template-columns: repeat(auto-fit,minmax(420px,1fr));
gap:25px;
}
.hivehub-card{
background:#1e1e2f;
border-radius:12px;
padding:20px;
border:1px solid rgba(255,255,255,0.05);
}
.hivehub-title{
font-size:14px;
color:#aaa;
}
.hivehub-value{
font-size:26px;
font-weight:bold;
color:#fff;
margin-bottom:10px;
}
</style>
<div class="hivehub-grid">
<div class="hivehub-card">
<div class="hivehub-title">Hive Power</div>
<div class="hivehub-value" id="hpValue">...</div>
<canvas id="hpChart"></canvas>
</div>
<div class="hivehub-card">
<div class="hivehub-title">HP Delta</div>
<div class="hivehub-value" id="hpDeltaValue">...</div>
<canvas id="hpDeltaChart"></canvas>
</div>
<div class="hivehub-card">
<div class="hivehub-title">Author Rewards</div>
<div class="hivehub-value" id="authorValue">...</div>
<canvas id="authorChart"></canvas>
</div>
<div class="hivehub-card">
<div class="hivehub-title">Curation Rewards</div>
<div class="hivehub-value" id="curationValue">...</div>
<canvas id="curationChart"></canvas>
</div>
</div>
<script>
async function loadHiveHubExact() {
try {
const username = localStorage.getItem('hive_account') || '';
// ===== GLOBAL PROPS =====
const propsRes = await fetch('https://api.hive.blog', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
jsonrpc:"2.0",
method:"condenser_api.get_dynamic_global_properties",
params:[],
id:1
})
});
const props = (await propsRes.json()).result;
const total_vesting_fund = parseFloat(props.total_vesting_fund_hive);
const total_vesting_shares = parseFloat(props.total_vesting_shares);
function vestsToHP(vests){
return (vests * total_vesting_fund) / total_vesting_shares;
}
// ===== ACCOUNT =====
const accRes = await fetch('https://api.hive.blog', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
jsonrpc:"2.0",
method:"condenser_api.get_accounts",
params:[[username]],
id:1
})
});
const accData = await accRes.json();
if (!accData.result || !accData.result[0]) return;
const acc = accData.result[0];
const totalVests =
parseFloat(acc.vesting_shares) +
parseFloat(acc.received_vesting_shares) -
parseFloat(acc.delegated_vesting_shares);
const currentHP = vestsToHP(totalVests);
document.getElementById('hpValue').innerText = currentHP.toFixed(0) + " HP";
// ===== HISTORY =====
const histRes = await fetch('https://api.hive.blog', {
method:'POST',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
jsonrpc:"2.0",
method:"account_history_api.get_account_history",
params:{ account: username, start:-1, limit:1000 },
id:1
})
});
const histData = await histRes.json();
if (!histData.result) return;
const history = histData.result.history;
let days = 30;
let now = Date.now();
let hpDelta = {};
let author = {};
let curation = {};
for(let i=0;i<days;i++){
let d = new Date(now - i*86400000).toISOString().slice(0,10);
hpDelta[d] = 0;
author[d] = 0;
curation[d] = 0;
}
history.forEach(e=>{
const op = e[1].op;
const ts = new Date(e[1].timestamp).getTime();
const day = new Date(ts).toISOString().slice(0,10);
if(!(day in hpDelta)) return;
// ===== CURATION =====
if(op[0]==="curation_reward"){
let vests = parseFloat(op[1].reward);
let hp = vestsToHP(vests);
if (!isNaN(hp)) {
curation[day]+=hp;
hpDelta[day]+=hp;
}
}
// ===== AUTHOR =====
if(op[0]==="author_reward"){
let total = 0;
if(op[1].hbd_payout) total += parseFloat(op[1].hbd_payout);
if(op[1].hive_payout) total += parseFloat(op[1].hive_payout);
if (!isNaN(total)) author[day]+=total;
}
// ===== POWER UP =====
if(op[0]==="transfer_to_vesting"){
let amount = parseFloat(op[1].amount);
if (!isNaN(amount)) hpDelta[day]+=amount;
}
// ===== POWER DOWN =====
if(op[0]==="fill_vesting_withdraw"){
let amount = parseFloat(op[1].withdrawn);
if (!isNaN(amount)) hpDelta[day]-=amount;
}
});
let labels = Object.keys(hpDelta).reverse();
let cumulative = currentHP;
let hpData = [];
labels.forEach(d=>{
cumulative -= hpDelta[d];
hpData.push(cumulative);
});
hpData.reverse();
// ===== VALUES =====
document.getElementById('hpDeltaValue').innerText =
Object.values(hpDelta).reduce((a,b)=>a+b,0).toFixed(0)+" HP";
document.getElementById('authorValue').innerText =
Object.values(author).reduce((a,b)=>a+b,0).toFixed(2)+" HBD";
document.getElementById('curationValue').innerText =
Object.values(curation).reduce((a,b)=>a+b,0).toFixed(2)+" HP";
const baseOptions = {
responsive:true,
plugins:{legend:{display:false}},
scales:{
x:{ticks:{color:'#777'}},
y:{ticks:{color:'#777'}}
}
};
new Chart(hpChart,{
type:'line',
data:{labels,datasets:[{data:hpData,borderColor:'#00ff88',tension:0.3}]},
options:baseOptions
});
new Chart(hpDeltaChart,{
type:'bar',
data:{labels,datasets:[{data:Object.values(hpDelta).reverse(),backgroundColor:'#00ff8855'}]},
options:baseOptions
});
new Chart(authorChart,{
type:'bar',
data:{labels,datasets:[{data:Object.values(author).reverse(),backgroundColor:'#00d4ff88'}]},
options:baseOptions
});
new Chart(curationChart,{
type:'bar',
data:{labels,datasets:[{data:Object.values(curation).reverse(),backgroundColor:'#00ff8888'}]},
options:baseOptions
});
} catch (e) {
console.error("🔥 HiveHub error:", e);
}
}
document.addEventListener('DOMContentLoaded', loadHiveHubExact);
</script>
I managed to add a table at the bottom of my code to display a copy-paste of:
https://hivehub.dev/stats/account?username=we-are-ai&category=financial&days=30
My HP
My HP delta
My author reward
My curation reward
I improve it whenever I have time to build a fully automated curation bot .
And I’ll keep you posted if I have other ideas for things to add to the screen, or if you have any.
full code in comment