Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/Hashrate.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useSignals } from "@preact/signals-react/runtime";
import { useRef, useEffect, useState } from "react";
import { hashrate } from "./signals";
import { hashrate, miningStatus } from "./signals";

const fixed = (n: number) => n.toFixed(2);

Expand All @@ -10,6 +10,7 @@ const SMOOTHING_FACTOR = 0.15; // Lower = smoother but slower to react
export default function Hashrate() {
useSignals();
const rawValue = hashrate.value;
const status = miningStatus.value;
const smoothedRef = useRef(rawValue);
const [displayValue, setDisplayValue] = useState(rawValue);

Expand All @@ -25,6 +26,14 @@ export default function Hashrate() {

const value = displayValue;

// While mining is active but the first GPU batch hasn't yet completed (so
// we have no measured rate), show an explicit "warming up…" instead of a
// bare "0.00 H/s" — the latter looks like the miner is broken even though
// it's actually dispatching work. The first batch typically takes 3–8 s.
if ((status === "mining" || status === "change") && value === 0) {
return "warming up…";
}

if (value > 1000000000) {
return `${fixed(value / 1000000000)} Gh/s`;
} else if (value > 1000000) {
Expand Down
4 changes: 3 additions & 1 deletion src/Messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ export default function Messages() {
</>
)}
{m.type === "start" && <>Mining started</>}
{m.type === "stop" && <>Mining stopped</>}
{m.type === "stop" && (
<>Mining stopped{m.reason ? <> — {m.reason}</> : null}</>
)}
</Box>
</Line>
))}
Expand Down
45 changes: 35 additions & 10 deletions src/initWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,49 @@ contractsUrl.value =
useIndexerApi.value = localStorage.getItem("useIndexerApi") !== "";
// Load RXinDexer REST API URL
restApiUrl.value = localStorage.getItem("restApiUrl") || "https://glyph-miner.com/api";
// Default to enabled unless explicitly disabled
autoReseed.value = localStorage.getItem("autoReseed") !== "";

// If servers isn't saved then set to default servers, randomly sorted
// Also ensure any new default servers are added to stored list
// autoReseed default: ON. Honor an explicit "0" to disable; treat anything
// else (including missing / legacy empty string) as enabled. The previous
// check (`!== ""`) inverted the convention so writing "0" silently failed
// to disable — kept as a fallback for legacy stored values.
{
const stored = localStorage.getItem("autoReseed");
if (stored === null) {
autoReseed.value = true;
} else if (stored === "0") {
autoReseed.value = false;
} else if (stored === "") {
// Legacy form written by the old Settings UI; treat as disabled.
autoReseed.value = false;
} else {
autoReseed.value = true;
}
}

// If servers isn't saved then set to default servers in canonical order.
//
// On first run we seed the user's stored list with the defaults. On
// subsequent runs we respect the stored list as-is — we do NOT silently
// merge in any new defaults that the user previously removed, because that
// makes "remove server" stick for one session and reappear on the next.
// Users who want refreshed defaults can clear the entry from Settings or
// localStorage.
const storedServers = localStorage.getItem("servers");
if (storedServers) {
const parsed: string[] = JSON.parse(storedServers);
const missing = defaultServers.filter((s) => !parsed.includes(s));
if (missing.length > 0) {
parsed.push(...missing);
localStorage.setItem("servers", JSON.stringify(parsed));
try {
const parsed: string[] = JSON.parse(storedServers);
servers.value = Array.isArray(parsed) && parsed.length > 0
? parsed
: defaultServers.slice();
} catch {
// Corrupt JSON in storage — fall back to defaults rather than crash.
servers.value = defaultServers.slice();
}
servers.value = parsed;
} else {
// Deterministic order — first entries are Radiant Core nodes that
// accept V2 BLAKE3/K12 dMint contracts. See defaultServers comment.
servers.value = defaultServers.slice();
localStorage.setItem("servers", JSON.stringify(servers.value));
}

connect();
Binary file modified src/miner.ts
Binary file not shown.
2 changes: 1 addition & 1 deletion src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export default function Settings() {
mineToAddress: mineToAddress.value,
mintMessage: mintMessage.value,
hideMessages: hideMessages.value ? "1" : "",
autoReseed: autoReseed.value ? "1" : "",
autoReseed: autoReseed.value ? "1" : "0",
servers: servers.value.join("\n"),
contractsUrl: contractsUrl.value,
restApiUrl: restApiUrl.value,
Expand Down
10 changes: 9 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ export type Message = {
seconds: number;
}
| {
type: "start" | "stop";
type: "start";
}
| {
type: "stop";
// Optional human-readable reason. When present, the Messages UI
// renders it as "Mining stopped — {reason}" so the user knows why
// the miner halted (nonce exhaustion, GPU error, algo mismatch,
// etc.) instead of seeing the Start button silently toggle back on.
reason?: string;
}
);