Add graph telemetry and remote signer login
This commit is contained in:
@@ -16,6 +16,27 @@ const totalThs = computed(() => stats.snapshot?.pool.combinedHashrateThs ?? 0);
|
||||
const miners = computed(() => stats.snapshot?.miners ?? []);
|
||||
const errorMsg = computed(() => stats.error);
|
||||
const upstreamErr = computed(() => stats.snapshot?.error);
|
||||
|
||||
const bestWorkByMiner = computed(() => {
|
||||
const out: Record<string, number> = {};
|
||||
for (let i = 1; i < stats.history.length; i += 1) {
|
||||
const prev = stats.history[i - 1];
|
||||
const next = stats.history[i];
|
||||
if (!prev?.minerWork || !next?.minerWork || !prev.minerShares || !next.minerShares) continue;
|
||||
for (const [key, work] of Object.entries(next.minerWork)) {
|
||||
const shareDelta = (next.minerShares[key] ?? 0) - (prev.minerShares[key] ?? 0);
|
||||
const workDelta = work - (prev.minerWork[key] ?? work);
|
||||
if (shareDelta <= 0 || workDelta <= 0) continue;
|
||||
out[key] = Math.max(out[key] ?? 0, workDelta / shareDelta);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
});
|
||||
const poolBestWork = computed(() => Math.max(0, ...Object.values(bestWorkByMiner.value)));
|
||||
|
||||
function minerKey(m: { nickname: string; authUsername: string; remoteHost: string }): string {
|
||||
return m.nickname || m.authUsername || m.remoteHost;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -30,13 +51,28 @@ const upstreamErr = computed(() => stats.snapshot?.error);
|
||||
|
||||
<PoolHero :snapshot="stats.snapshot" />
|
||||
|
||||
<section class="best panel">
|
||||
<div>
|
||||
<div class="label">best accepted calculation observed</div>
|
||||
<strong class="glow-amber">
|
||||
{{ poolBestWork > 0 ? poolBestWork.toLocaleString(undefined, { maximumFractionDigits: 2 }) : "collecting" }}
|
||||
</strong>
|
||||
</div>
|
||||
<span class="muted">derived from accepted difficulty jumps while this browser has history</span>
|
||||
</section>
|
||||
|
||||
<div class="grid-row">
|
||||
<LotteryWidget :total-ths="totalThs" />
|
||||
<ShareTicker :snapshot="stats.snapshot" />
|
||||
</div>
|
||||
|
||||
<div class="miners">
|
||||
<MinerCard v-for="m in miners" :key="m.authUsername || m.nickname" :miner="m" />
|
||||
<MinerCard
|
||||
v-for="m in miners"
|
||||
:key="m.authUsername || m.nickname"
|
||||
:miner="m"
|
||||
:best-work="bestWorkByMiner[minerKey(m)]"
|
||||
/>
|
||||
<div v-if="!miners.length && !errorMsg" class="empty panel muted">
|
||||
waiting for the first poll · the boards are warming up
|
||||
</div>
|
||||
@@ -58,6 +94,22 @@ const upstreamErr = computed(() => stats.snapshot?.error);
|
||||
gap: 16px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.best {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.best strong {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 24px;
|
||||
}
|
||||
.best span {
|
||||
font-size: 11px;
|
||||
text-align: right;
|
||||
}
|
||||
.miners {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
@@ -70,5 +122,12 @@ const upstreamErr = computed(() => stats.snapshot?.error);
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.grid-row { grid-template-columns: 1fr; }
|
||||
.best {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
.best span {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user