Add transaction accelerator (prioritisetransaction UI + API)
Full-stack feature for boosting transactions via bitcoind's prioritisetransaction RPC: Backend: - New accelerator package with Accelerate, Cancel, MaxFeerate, List, and background Cleanup goroutine (removes confirmed/dropped txs) - RPC wrappers: GetMempoolEntry, PrioritiseTransaction, GetRawMempoolVerbose, IsRPCError helpers - SQLite boosted_txs table for persistence across restarts - Revenue impact measured via getblocktemplate before/after comparison - Hard cap at 2000 sat/vB; MaxFeerate uses fees.base (not modified) to ignore our own prior priority adjustments Frontend: - Rocket icon in header with 10s jiggle animation - AcceleratorPage with flame-gradient border, txid input, feerate input, "Prioritize above all" button with spinner, boost list with cancel buttons, and dismissible error/success messages - Hash-based routing (#/accelerator) - SharesBar font size bump
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// #/ -> dashboard
|
||||
// #/user/<address> -> per-user page
|
||||
// #/worker/<workername> -> per-worker page
|
||||
// #/accelerator -> transaction accelerator
|
||||
//
|
||||
// selectUser / selectWorker / clearSelection just mutate the hash;
|
||||
// a hashchange listener reads it back into reactive state so any
|
||||
@@ -10,29 +11,34 @@
|
||||
|
||||
const USER_PREFIX = "#/user/";
|
||||
const WORKER_PREFIX = "#/worker/";
|
||||
const ACCELERATOR_HASH = "#/accelerator";
|
||||
|
||||
type Selection = { user: string | null; worker: string | null };
|
||||
type Selection = { user: string | null; worker: string | null; page: string | null };
|
||||
|
||||
export const selection = $state<Selection>(readHash());
|
||||
|
||||
function readHash(): Selection {
|
||||
if (typeof window === "undefined") return { user: null, worker: null };
|
||||
if (typeof window === "undefined") return { user: null, worker: null, page: null };
|
||||
const h = window.location.hash;
|
||||
if (h === ACCELERATOR_HASH) {
|
||||
return { user: null, worker: null, page: "accelerator" };
|
||||
}
|
||||
if (h.startsWith(WORKER_PREFIX)) {
|
||||
const w = decodeURIComponent(h.slice(WORKER_PREFIX.length));
|
||||
return { user: null, worker: w || null };
|
||||
return { user: null, worker: w || null, page: null };
|
||||
}
|
||||
if (h.startsWith(USER_PREFIX)) {
|
||||
const u = decodeURIComponent(h.slice(USER_PREFIX.length));
|
||||
return { user: u || null, worker: null };
|
||||
return { user: u || null, worker: null, page: null };
|
||||
}
|
||||
return { user: null, worker: null };
|
||||
return { user: null, worker: null, page: null };
|
||||
}
|
||||
|
||||
function syncFromHash(): void {
|
||||
const parsed = readHash();
|
||||
selection.user = parsed.user;
|
||||
selection.worker = parsed.worker;
|
||||
selection.page = parsed.page;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
@@ -47,11 +53,16 @@ export function selectWorker(workername: string): void {
|
||||
window.location.hash = WORKER_PREFIX + encodeURIComponent(workername);
|
||||
}
|
||||
|
||||
export function selectAccelerator(): void {
|
||||
window.location.hash = ACCELERATOR_HASH;
|
||||
}
|
||||
|
||||
export function clearSelection(): void {
|
||||
if (
|
||||
window.history.length > 1 &&
|
||||
(window.location.hash.startsWith(USER_PREFIX) ||
|
||||
window.location.hash.startsWith(WORKER_PREFIX))
|
||||
window.location.hash.startsWith(WORKER_PREFIX) ||
|
||||
window.location.hash === ACCELERATOR_HASH)
|
||||
) {
|
||||
window.history.back();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user