mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-07 17:18:13 -07:00
179 lines
5.5 KiB
JavaScript
179 lines
5.5 KiB
JavaScript
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),
|
|
),
|
|
),
|
|
);
|
|
}
|