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 client/src/components/info-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const InfoCard = ({
footer,
body,
className,
infoCardHeaderValueClass,
} = {}) => (
<div
className={
Expand All @@ -27,7 +28,15 @@ export const InfoCard = ({
/>
) : null}
{headerValue !== undefined ? (
<p className="info-card-header-value">{headerValue}</p>
<span
className={
infoCardHeaderValueClass
? `info-card-header-value ${infoCardHeaderValueClass}`
: "info-card-header-value"
}
>
{headerValue}
</span>
) : null}
</div>
{value !== undefined ? <p className="info-card-value">{value}</p> : null}
Expand Down
4 changes: 2 additions & 2 deletions client/src/lib/pending-block-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ export const formatPanelPercentage = (value, fallback = "N/A") =>
export const formatFeeBoundary = (value, fallback = "N/A") =>
Number.isFinite(value) ? value.toFixed(2) : fallback;

export const formatWeight = (value, fallback = "N/A") =>
export const formatWeight = (value, fallback = "N/A", omitSuffix = false) =>
Number.isFinite(value)
? `${formatTrimmedDecimal(value / 1_000_000)} MWU`
? `${formatTrimmedDecimal(value / 1_000_000)} ${omitSuffix ? "" : "MWU"}`
: fallback;

export const formatMegabytes = (value, fallback = "N/A") =>
Expand Down
39 changes: 38 additions & 1 deletion client/src/views/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@ import { formatFeeRate, formatUsd } from "./util";

const staticRoot = process.env.STATIC_ROOT || "";

const getPercentDelta = (chartPrices, unavailable = "N/A") => {
if (!Array.isArray(chartPrices) || chartPrices.length < 2) {
return unavailable;
}

const startingPrice = chartPrices[0];
const endingPrice = chartPrices[chartPrices.length - 1];

if (
!Number.isFinite(startingPrice) ||
startingPrice === 0 ||
!Number.isFinite(endingPrice)
) {
return unavailable;
}

const priceDeltaPercentage =
((endingPrice - startingPrice) / startingPrice) * 100;

if (!Number.isFinite(priceDeltaPercentage)) {
return unavailable;
}

const formattedPercentage = priceDeltaPercentage.toFixed(2);

if (priceDeltaPercentage < 0) {
return <span className="text-danger">{`${formattedPercentage}%`}</span>;
}

return <span className="text-success">{`+${formattedPercentage}%`}</span>;
};

const getChartPrices = (marketChart) =>
getBitcoinPrices(marketChart).slice(-24);

Expand Down Expand Up @@ -76,7 +108,12 @@ export const overview = ({
<InfoCard
title={t`Bitcoin`}
iconSrc={`${staticRoot}img/icons/Bitcoin-menu-logo.svg`}
headerValue={formatUsd(currentBitcoinPrice, t`N/A`)}
headerValue={
<span className="overview-bitcoin-price-chart-header-value">
<span>{formatUsd(currentBitcoinPrice, t`N/A`)}</span>
{getPercentDelta(chartPrices, t`N/A`)}
</span>
}
body={
<ReferenceLineChart
className="overview-bitcoin-price-chart"
Expand Down
10 changes: 6 additions & 4 deletions client/src/views/pending-block-details-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,12 +552,13 @@ const PendingBlockDetailsCard = ({
tooltip={t`Transactions currently selected for the pending block, including the coinbase transaction.`}
headerValue={
metrics ? (
<StatusBadge variant="success">
<StatusDot />
<span>{t`Live`}</span>
</StatusBadge>
<StatusBadge variant="success">
<StatusDot />
<span>{t`Live`}</span>
</StatusBadge>
) : undefined
}
infoCardHeaderValueClass="block-transactions-status-badge-container"
value={
<span className="pending-block-transaction-value">
<span>
Expand Down Expand Up @@ -680,6 +681,7 @@ const PendingBlockDetailsCard = ({
? `${formatWeight(
metrics.totalWeight,
unavailable,
true
)} / ${formatWeight(
metrics.weightLimit,
unavailable,
Expand Down
1 change: 1 addition & 0 deletions flavors/liquid/extras.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
--surface-primary-color: #0C1537;
--surface-secondary-color: #172146;
--surface-primary-alt-color: #111F3C;
--field-border-color: #172146;
}

.search-bar {
Expand Down
29 changes: 28 additions & 1 deletion test/overview.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test("formats the recommended fee rate and dollar estimate", () => {
blocks: [],
feeEst: { 3: 6 },
mempool: { vsize: 0 },
bitcoinMarketChart: { prices: [[1, 50_000]] },
bitcoinMarketChart: { prices: [[1, 40_000], [2, 50_000]] },
t,
}));

Expand All @@ -27,6 +27,33 @@ test("formats the recommended fee rate and dollar estimate", () => {
);
assert(html.includes(expectedFeeUsd), expectedFeeUsd);
assert.match(html, /\$50,000\.00 USD/);
assert.match(html, /\+25\.00%/);
});

test("formats negative Bitcoin price changes", () => {
const html = render(overview({
blocks: [],
bitcoinMarketChart: { prices: [[1, 50_000], [2, 40_000]] },
t,
}));

assert.match(html, /class="text-danger">-20\.00%/);
});

test("shows an unavailable Bitcoin price change without a valid baseline", () => {
const singlePriceHtml = render(overview({
blocks: [],
bitcoinMarketChart: { prices: [[1, 50_000]] },
t,
}));
const zeroBaselineHtml = render(overview({
blocks: [],
bitcoinMarketChart: { prices: [[1, 0], [2, 50_000]] },
t,
}));

assert.match(singlePriceHtml, /\$50,000\.00 USD<\/span>N\/A/);
assert.match(zeroBaselineHtml, /\$50,000\.00 USD<\/span>N\/A/);
});

test("shows unavailable overview fee and price values explicitly", () => {
Expand Down
50 changes: 42 additions & 8 deletions www/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2711,6 +2711,7 @@ dl.mempool-histogram .bar:before {
background-color: var(--surface-primary-color);
border-radius: 8px;
padding: 12px 16px;
border: 1px solid var(--field-border-color);
}

.network-hover-menu-option-container {
Expand Down Expand Up @@ -3483,7 +3484,6 @@ a.back-link img{
.tooltip {
display: flex;
position: relative;
margin-left: 6px;
padding: 0;
border: 0;
color: inherit;
Expand Down Expand Up @@ -3515,7 +3515,7 @@ a.back-link img{
max-width: 200px;
padding: 6px;
border-radius: 4px;
background-color: var(--surface-secondary-color);
background-color: var(--surface-primary-color);
font-size: 14px;
color: #FAFAFA;
top: 10px;
Expand All @@ -3524,7 +3524,7 @@ a.back-link img{
white-space: normal;
overflow-wrap: anywhere;
z-index: 999;
border: .5px solid var(--field-border-color);
border: 1px solid var(--field-border-color);
}

@media only screen and (min-width: 1329px) {
Expand Down Expand Up @@ -3702,6 +3702,7 @@ a.back-link img{
.usage-and-tooltip {
display: flex;
align-items: center;
gap: 6px;
}

.usage-number {
Expand Down Expand Up @@ -3885,11 +3886,12 @@ a.back-link img{
.table-header {
display: flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}

.table-header-title {
margin-left: 16px;
margin-left: 10px;
color: #B5BDC2;
font-family: "Rigid Square", sans-serif;
font-size: 20px;
Expand Down Expand Up @@ -4193,6 +4195,11 @@ a.back-link img{
font-size: 10px;
}

.overview-bitcoin-price-chart-header-value {
display: flex;
gap: 4px;
}

.overview-bitcoin-price-chart {
height: 100%;
width: 100%;
Expand Down Expand Up @@ -4494,6 +4501,7 @@ a.back-link img{
.block-details-card-progress-title {
display: flex;
align-items: center;
gap: 6px;
}

.block-details-card-progress-header .usage-number {
Expand Down Expand Up @@ -4913,6 +4921,26 @@ a.back-link img{
.asset-table-issuance-link {
margin-left: 0;
}

.overview-fees {
flex-direction: column;
gap: 0px;
align-items: initial;
}

.transaction-table-footer-confirmation-text{
flex-wrap: wrap;
}

.info-card-header {
flex-wrap: wrap;
}
}

@media only screen and (max-width: 485px) {
.block-transactions-status-badge-container {
width: 100%;
}
}

.pending-block-details-card {
Expand Down Expand Up @@ -5248,6 +5276,7 @@ a.back-link img{
flex: .55;
flex-direction: column;
gap: 12px;
margin-top: 12px;
}

.expanded-pending-block-row {
Expand Down Expand Up @@ -5412,6 +5441,7 @@ a.back-link img{
@media only screen and (max-width: 1328px) {
.overview-body {
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: none;
-ms-overflow-style: none;
}
Expand All @@ -5433,10 +5463,6 @@ a.back-link img{
font-size: 14px;
}

.expanded-pending-block-row {
flex-direction: column;
}

.pending-block-container {
width: 100%;
height: auto;
Expand Down Expand Up @@ -5759,6 +5785,10 @@ a.back-link img{
margin-left: auto;
margin-right: auto;
}

.metric-bar-header-value {
font-size: 12px;
}
}

@media only screen and (max-width: 1328px) {
Expand Down Expand Up @@ -5988,4 +6018,8 @@ a.blockstream-footer-contact:focus {
.blockstream-footer-product-columns {
column-gap: 24px;
}

.table-title-row {
display: none;
}
}