mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-19 14:24:47 -07:00
website: snap
This commit is contained in:
@@ -63,6 +63,9 @@
|
||||
* @typedef {Brk.AddrStats} AddrStats
|
||||
* @typedef {Brk.TxIn} TxIn
|
||||
* @typedef {Brk.TxOut} TxOut
|
||||
* @typedef {Brk.BlockTemplate} BlockTemplate
|
||||
* @typedef {Brk.MempoolBlock} MempoolBlock
|
||||
* @typedef {Brk.NextBlockHash} NextBlockHash
|
||||
* ActivePriceRatioPattern: ratio pattern with price (extended)
|
||||
* @typedef {Brk.BpsPriceRatioPattern} ActivePriceRatioPattern
|
||||
* PriceRatioPercentilesPattern: price pattern with ratio + percentiles (no SMAs/stdDev)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { brk } from "../utils/client.js";
|
||||
import { onPlainClick } from "../utils/dom.js";
|
||||
import { createCube } from "./cube.js";
|
||||
import { initMempool, renderMempool } from "./mempool.js";
|
||||
import { createHeightElement, formatFeeRate } from "./render.js";
|
||||
|
||||
const LOOKAHEAD = 15;
|
||||
@@ -59,6 +60,8 @@ export function initChain(parent, callbacks) {
|
||||
blocksEl.classList.add("blocks");
|
||||
scrollEl.append(blocksEl);
|
||||
|
||||
initMempool(scrollEl);
|
||||
|
||||
olderObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0].isIntersecting) loadOlder();
|
||||
@@ -208,7 +211,10 @@ export async function goToCube(hashOrHeight, { silent } = {}) {
|
||||
}
|
||||
|
||||
export async function poll() {
|
||||
if (newestHeight === -1 || !reachedTip) return;
|
||||
if (!reachedTip) return;
|
||||
brk.getMempoolBlocks()
|
||||
.then(renderMempool)
|
||||
.catch((e) => console.error("mempool poll:", e));
|
||||
try {
|
||||
const blocks = await brk.getBlocksV1();
|
||||
appendNewerBlocks(blocks);
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
poll,
|
||||
selectCube,
|
||||
deselectCube,
|
||||
} from "./chain.js";
|
||||
} from "../../src/explorer/chain/index.js";
|
||||
import {
|
||||
initBlockDetails,
|
||||
update as updateBlock,
|
||||
|
||||
89
website/scripts/explorer/mempool.js
Normal file
89
website/scripts/explorer/mempool.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import { createCube } from "./cube.js";
|
||||
import { formatFeeRate } from "./render.js";
|
||||
|
||||
const NUM_BLOCKS = 8;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* el: HTMLElement,
|
||||
* topFace: HTMLDivElement,
|
||||
* rightFace: HTMLDivElement,
|
||||
* leftFace: HTMLDivElement,
|
||||
* }} Cube
|
||||
*/
|
||||
|
||||
/** @type {HTMLDivElement | null} */ let mempoolBlocksEl = null;
|
||||
/** @type {Cube[]} */ const cubes = [];
|
||||
|
||||
/** @param {HTMLElement} parent the `.chain-scroll` element */
|
||||
export function initMempool(parent) {
|
||||
mempoolBlocksEl = document.createElement("div");
|
||||
mempoolBlocksEl.classList.add("mempool-blocks");
|
||||
mempoolBlocksEl.hidden = true;
|
||||
parent.prepend(mempoolBlocksEl);
|
||||
}
|
||||
|
||||
/** @param {MempoolBlock[]} blocks */
|
||||
export function renderMempool(blocks) {
|
||||
if (!mempoolBlocksEl) return;
|
||||
mempoolBlocksEl.hidden = blocks.length === 0;
|
||||
const want = Math.min(blocks.length, NUM_BLOCKS);
|
||||
while (cubes.length > want) {
|
||||
const last = cubes.pop();
|
||||
if (last) last.el.remove();
|
||||
}
|
||||
while (cubes.length < want) {
|
||||
const cube = createMempoolCube(cubes.length);
|
||||
cubes.push(cube);
|
||||
mempoolBlocksEl.append(cube.el);
|
||||
}
|
||||
for (let i = 0; i < want; i++) updateMempoolCube(cubes[i], blocks[i], i);
|
||||
}
|
||||
|
||||
/** @param {number} position @returns {Cube} */
|
||||
function createMempoolCube(position) {
|
||||
const el = document.createElement("div");
|
||||
el.classList.add("cube", "projected");
|
||||
if (position === 0) el.classList.add("next");
|
||||
const { topFace, rightFace, leftFace } = createCube(el, 0);
|
||||
return { el, topFace, rightFace, leftFace };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Cube} cube
|
||||
* @param {MempoolBlock} block
|
||||
* @param {number} position
|
||||
*/
|
||||
function updateMempoolCube(cube, block, position) {
|
||||
const fill = Math.min(1, block.blockVSize / 1_000_000);
|
||||
cube.el.style.setProperty("--fill", String(fill));
|
||||
|
||||
cube.topFace.textContent = "";
|
||||
const label = document.createElement("p");
|
||||
label.textContent = position === 0 ? "next" : `+${position}`;
|
||||
cube.topFace.append(label);
|
||||
|
||||
cube.rightFace.textContent = "";
|
||||
const txs = document.createElement("p");
|
||||
txs.textContent = block.nTx.toLocaleString();
|
||||
const txsUnit = document.createElement("p");
|
||||
txsUnit.classList.add("dim");
|
||||
txsUnit.textContent = block.nTx === 1 ? "tx" : "txs";
|
||||
cube.rightFace.append(txs, txsUnit);
|
||||
|
||||
cube.leftFace.textContent = "";
|
||||
const median = document.createElement("p");
|
||||
const tilde = document.createElement("span");
|
||||
tilde.classList.add("dim");
|
||||
tilde.textContent = "~";
|
||||
median.append(tilde, formatFeeRate(block.medianFee));
|
||||
const range = document.createElement("p");
|
||||
const dash = document.createElement("span");
|
||||
dash.classList.add("dim");
|
||||
dash.textContent = "-";
|
||||
range.append(formatFeeRate(block.feeRange[0]), dash, formatFeeRate(block.feeRange[6]));
|
||||
const unit = document.createElement("p");
|
||||
unit.classList.add("dim");
|
||||
unit.textContent = "sat/vB";
|
||||
cube.leftFace.append(median, range, unit);
|
||||
}
|
||||
Reference in New Issue
Block a user