mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-08 01:28:15 -07:00
website_next: part 2
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import { createPoolLogo, getPoolDisplayName } from "../../pools/index.js";
|
||||
import { formatFeeRate } from "../../utils/fee-rate.js";
|
||||
import { createCubeButton, createCubeDiv } from "./cube/index.js";
|
||||
import { onPlainClick } from "./events.js";
|
||||
import {
|
||||
createHeightElement,
|
||||
dim,
|
||||
formatHHMM,
|
||||
formatShortDate,
|
||||
} from "./format.js";
|
||||
|
||||
/** @typedef {import("../../modules/brk-client/index.js").BlockInfoV1} Block */
|
||||
/** @typedef {import("../../modules/brk-client/index.js").MempoolBlock} MempoolBlock */
|
||||
|
||||
export function createPlaceholderCube() {
|
||||
const cube = document.createElement("div");
|
||||
|
||||
cube.dataset.cube = "";
|
||||
cube.dataset.placeholder = "";
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Block} block
|
||||
* @param {(cube: HTMLButtonElement) => void} onSelect
|
||||
*/
|
||||
export function createEnteringConfirmedCube(block, onSelect) {
|
||||
const cube = createConfirmedCube(block, onSelect);
|
||||
|
||||
markCubeEntering(cube);
|
||||
|
||||
return cube;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Block} block
|
||||
* @param {(cube: HTMLButtonElement) => void} onSelect
|
||||
*/
|
||||
function createConfirmedCube(block, onSelect) {
|
||||
const { pool, medianFee, feeRange, virtualSize } = block.extras;
|
||||
const cube = createCubeButton(Math.min(1, virtualSize / 1_000_000));
|
||||
|
||||
cube.element.dataset.hash = block.id;
|
||||
cube.element.dataset.height = String(block.height);
|
||||
cube.element.dataset.timestamp = String(block.timestamp);
|
||||
cube.element.title = `Block ${block.height.toLocaleString()}`;
|
||||
onPlainClick(cube.element, () => onSelect(cube.element));
|
||||
|
||||
const date = document.createElement("p");
|
||||
const time = document.createElement("p");
|
||||
const [hh, mm] = formatHHMM(block.timestamp);
|
||||
date.textContent = formatShortDate(block.timestamp);
|
||||
time.append(hh, dim(":"), mm);
|
||||
cube.topFace.append(date, time);
|
||||
|
||||
const height = document.createElement("p");
|
||||
height.dataset.cubeHeight = "";
|
||||
height.append(createHeightElement(block.height));
|
||||
|
||||
const poolElement = document.createElement("div");
|
||||
const logo = createPoolLogo(pool);
|
||||
const name = document.createElement("span");
|
||||
poolElement.dataset.cubePool = "";
|
||||
name.textContent = getPoolDisplayName(pool.name);
|
||||
poolElement.append(logo, name);
|
||||
cube.rightFace.append(height, poolElement);
|
||||
|
||||
const fees = document.createElement("div");
|
||||
const median = document.createElement("p");
|
||||
const range = document.createElement("p");
|
||||
const unit = document.createElement("p");
|
||||
fees.dataset.cubeFees = "";
|
||||
median.append(dim("~"), formatFeeRate(medianFee));
|
||||
range.append(
|
||||
formatFeeRate(feeRange[0]),
|
||||
dim("-"),
|
||||
formatFeeRate(feeRange[6]),
|
||||
);
|
||||
unit.dataset.dim = "";
|
||||
unit.textContent = "sat/vB";
|
||||
fees.append(median, range, unit);
|
||||
cube.leftFace.append(fees);
|
||||
|
||||
return cube.element;
|
||||
}
|
||||
|
||||
/** @param {HTMLElement} cube */
|
||||
function markCubeEntering(cube) {
|
||||
cube.dataset.enter = "";
|
||||
cube.addEventListener(
|
||||
"animationend",
|
||||
() => {
|
||||
cube.removeAttribute("data-enter");
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
}
|
||||
|
||||
export function createProjectedCube() {
|
||||
const cube = createCubeDiv();
|
||||
const date = document.createTextNode("");
|
||||
const hh = document.createTextNode("");
|
||||
const mm = document.createTextNode("");
|
||||
const txs = document.createTextNode("");
|
||||
const txsUnit = document.createTextNode("");
|
||||
const median = document.createTextNode("");
|
||||
const rangeLo = document.createTextNode("");
|
||||
const rangeHi = document.createTextNode("");
|
||||
|
||||
const dateElement = document.createElement("p");
|
||||
const timeElement = document.createElement("p");
|
||||
const txsElement = document.createElement("p");
|
||||
const txsUnitElement = document.createElement("p");
|
||||
const medianElement = document.createElement("p");
|
||||
const rangeElement = document.createElement("p");
|
||||
const unitElement = document.createElement("p");
|
||||
|
||||
cube.element.dataset.projected = "";
|
||||
dateElement.append(date);
|
||||
timeElement.append(hh, dim(":"), mm);
|
||||
cube.topFace.append(dateElement, timeElement);
|
||||
|
||||
txsElement.append(txs);
|
||||
txsUnitElement.dataset.dim = "";
|
||||
txsUnitElement.append(txsUnit);
|
||||
cube.rightFace.append(txsElement, txsUnitElement);
|
||||
|
||||
medianElement.append(dim("~"), median);
|
||||
rangeElement.append(rangeLo, dim("-"), rangeHi);
|
||||
unitElement.dataset.dim = "";
|
||||
unitElement.textContent = "sat/vB";
|
||||
cube.leftFace.append(medianElement, rangeElement, unitElement);
|
||||
|
||||
return {
|
||||
...cube,
|
||||
parts: { date, hh, mm, txs, txsUnit, median, rangeLo, rangeHi },
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {ReturnType<typeof createProjectedCube>} cube @param {MempoolBlock} block */
|
||||
export function updateProjectedCube(cube, block) {
|
||||
cube.element.style.setProperty(
|
||||
"--fill",
|
||||
String(Math.min(1, block.blockVSize / 1_000_000)),
|
||||
);
|
||||
|
||||
cube.parts.txs.nodeValue = block.nTx.toLocaleString();
|
||||
cube.parts.txsUnit.nodeValue = block.nTx === 1 ? "tx" : "txs";
|
||||
cube.parts.median.nodeValue = formatFeeRate(block.medianFee);
|
||||
cube.parts.rangeLo.nodeValue = formatFeeRate(block.feeRange[0]);
|
||||
cube.parts.rangeHi.nodeValue = formatFeeRate(block.feeRange[6]);
|
||||
}
|
||||
|
||||
/** @param {ReturnType<typeof createProjectedCube>} cube @param {number} timestamp */
|
||||
export function updateProjectedTime(cube, timestamp) {
|
||||
const [hh, mm] = formatHHMM(timestamp);
|
||||
|
||||
cube.parts.date.nodeValue = formatShortDate(timestamp);
|
||||
cube.parts.hh.nodeValue = hh;
|
||||
cube.parts.mm.nodeValue = mm;
|
||||
}
|
||||
|
||||
/** @param {HTMLElement} cube */
|
||||
export function setConfirmedInterval(cube) {
|
||||
const prev = /** @type {HTMLElement | null} */ (cube.previousElementSibling);
|
||||
if (!prev?.dataset.timestamp) return;
|
||||
|
||||
cube.style.setProperty(
|
||||
"--block-interval",
|
||||
String(
|
||||
Math.max(
|
||||
0,
|
||||
Number(cube.dataset.timestamp) - Number(prev.dataset.timestamp),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user