Skip to content

Commit

Permalink
fix: Update charts to use best te unit for values (#527)
Browse files Browse the repository at this point in the history
* fix: Update `DailyAvgBlobFeeChart` and `DailyAvgBlobGasPriceChart` to use best unit for values

* chore: update changeset

* Revert `prettyFormatWei` function

* feat: Adds useArrayBestUnit

* fix: Update DailyAvgBlobFeeChart to use best unit for values

* feat: Update DailyAvgMaxBlobGasFeeChart to use formatted number in yAxisTooltip

* feat: Adds yAxisLabel DailyAvgMaxBlobGasFeeChart

* chore: Added EthAmount

* refactor: useArrayBestUnit

* refactor: useScaledWeiAmounts nitpicks

* refactor: Update `countIntegerDigits` function to handle scientific notation in eth-format

* feat: Update yAxisLabel in DailyAvgBlobFeeChart, DailyAvgBlobGasPriceChart, DailyBlobFeeChart and
DailyAvgMaxBlobGasFeeChart

* chore: Update DailyAvgMaxBlobGasFeeChart grid configuration

* chore: Update grid configuration for DailyAvgBlobFeeChart, DailyAvgBlobGasPriceChart, and DailyBlobFeeChart
  • Loading branch information
luis-herasme authored Sep 4, 2024
1 parent 399c98c commit c9a6ada
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-roses-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blobscan/web": patch
---

Updated `DailyAvgBlobFeeChart` and `DailyAvgBlobGasPriceChart` to use the best unit for values
17 changes: 8 additions & 9 deletions apps/web/src/components/Charts/Block/DailyAvgBlobFeeChart.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import type { FC } from "react";
import { useMemo } from "react";
import type { EChartOption } from "echarts";

import { convertWei } from "@blobscan/eth-units";

import { ChartCard } from "~/components/Cards/ChartCard";
import { useScaledWeiAmounts } from "~/hooks/useScaledWeiAmounts";
import type { DailyBlockStats } from "~/types";
import { formatNumber } from "~/utils";
import { buildTimeSeriesOptions } from "~/utils";
Expand All @@ -16,23 +14,24 @@ export type DailyAvgBlobFeeChartProps = {

export const DailyAvgBlobFeeChart: FC<Partial<DailyAvgBlobFeeChartProps>> =
function ({ days, avgBlobFees }) {
const formattedAvgBlobFees = useMemo(
() => avgBlobFees?.map((fee) => convertWei(fee)),
[avgBlobFees]
);
const { scaledValues, unit } = useScaledWeiAmounts(avgBlobFees);

const options: EChartOption<EChartOption.SeriesBar> = {
...buildTimeSeriesOptions({
dates: days,
axisFormatters: {
yAxisTooltip: (value) => `${formatNumber(value)} Gwei`,
yAxisTooltip: (value) => `${formatNumber(value)} ${unit}`,
yAxisLabel: (value) => `${formatNumber(value)} ${unit}`,
},
yUnit: "ethereum",
}),
grid: {
containLabel: true,
},
series: [
{
name: "Avg. Blob Fees",
data: formattedAvgBlobFees,
data: scaledValues,
type: "bar",
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import type { FC } from "react";
import { useMemo } from "react";
import type { EChartOption } from "echarts";

import { convertWei } from "@blobscan/eth-units";

import { ChartCard } from "~/components/Cards/ChartCard";
import { useScaledWeiAmounts } from "~/hooks/useScaledWeiAmounts";
import type { DailyBlockStats } from "~/types";
import { buildTimeSeriesOptions, formatNumber } from "~/utils";

Expand All @@ -16,23 +14,24 @@ export type DailyAvgBlobGasPriceChartProps = {
export const DailyAvgBlobGasPriceChart: FC<
Partial<DailyAvgBlobGasPriceChartProps>
> = function ({ days, avgBlobGasPrices }) {
const formattedAvgBlobGasPrices = useMemo(
() => avgBlobGasPrices?.map((price) => convertWei(price)),
[avgBlobGasPrices]
);
const { scaledValues, unit } = useScaledWeiAmounts(avgBlobGasPrices);

const options: EChartOption<EChartOption.SeriesBar> = {
...buildTimeSeriesOptions({
dates: days,
axisFormatters: {
yAxisTooltip: (value) => `${formatNumber(value)} Gwei`,
yAxisTooltip: (value) => `${formatNumber(value)} ${unit}`,
yAxisLabel: (value) => `${formatNumber(value)} ${unit}`,
},
yUnit: "ethereum",
}),
grid: {
containLabel: true,
},
series: [
{
name: "Avg. Blob Gas Prices",
data: formattedAvgBlobGasPrices,
data: scaledValues,
type: "bar",
},
],
Expand Down
18 changes: 10 additions & 8 deletions apps/web/src/components/Charts/Block/DailyBlobFeeChart.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import type { FC } from "react";
import { useMemo } from "react";
import type { EChartOption } from "echarts";

import { convertWei } from "@blobscan/eth-units";

import { ChartCard } from "~/components/Cards/ChartCard";
import { useScaledWeiAmounts } from "~/hooks/useScaledWeiAmounts";
import type { DailyBlockStats } from "~/types";
import { formatNumber } from "~/utils";
import { buildTimeSeriesOptions } from "~/utils";
Expand All @@ -16,22 +14,26 @@ export type DailyBlobFeeChartProps = {

export const DailyBlobFeeChart: FC<Partial<DailyBlobFeeChartProps>> =
function ({ days, blobFees }) {
const formattedBlobFees = useMemo(
() => blobFees?.map((fee) => convertWei(BigInt(fee))),
[blobFees]
const { scaledValues, unit } = useScaledWeiAmounts(
blobFees?.map((x) => Number(x))
);

const options: EChartOption<EChartOption.SeriesBar> = {
...buildTimeSeriesOptions({
dates: days,
axisFormatters: {
yAxisTooltip: (value) => `${formatNumber(value)} Gwei`,
yAxisTooltip: (value) => `${formatNumber(value)} ${unit}`,
yAxisLabel: (value) => `${formatNumber(value)} ${unit}`,
},
yUnit: "ethereum",
}),
grid: {
containLabel: true,
},
series: [
{
name: "Blob Fees",
data: formattedBlobFees,
data: scaledValues,
type: "bar",
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { FC } from "react";
import type { EChartOption } from "echarts";

import { formatWei } from "@blobscan/eth-units";

import { ChartCard } from "~/components/Cards/ChartCard";
import { useScaledWeiAmounts } from "~/hooks/useScaledWeiAmounts";
import type { DailyTransactionStats } from "~/types";
import { buildTimeSeriesOptions } from "~/utils";
import { buildTimeSeriesOptions, formatNumber } from "~/utils";

export type DailyAvgMaxBlobGasFeeChartProps = {
days: DailyTransactionStats["days"];
Expand All @@ -16,20 +15,25 @@ export type DailyAvgMaxBlobGasFeeChartProps = {
export const DailyAvgMaxBlobGasFeeChart: FC<
Partial<DailyAvgMaxBlobGasFeeChartProps>
> = function ({ days, avgMaxBlobGasFees, compact = false }) {
const { scaledValues, unit } = useScaledWeiAmounts(avgMaxBlobGasFees);

const options: EChartOption<
EChartOption.SeriesBar | EChartOption.SeriesLine
> = {
...buildTimeSeriesOptions({
dates: days,
axisFormatters: {
yAxisTooltip: (value) => formatWei(value),
yAxisLabel: (value) => formatWei(value),
yAxisTooltip: (value) => `${formatNumber(value)} ${unit}`,
yAxisLabel: (value) => `${formatNumber(value)} ${unit}`,
},
}),
grid: {
containLabel: true,
},
series: [
{
name: "Avg. Max Blob Gas Fees",
data: avgMaxBlobGasFees,
data: scaledValues,
type: compact ? "line" : "bar",
smooth: true,
},
Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/hooks/useScaledWeiAmounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useMemo } from "react";

import type { EtherUnit } from "@blobscan/eth-units";
import { convertWei, findBestUnit } from "@blobscan/eth-units";

type ScaledWeiAmounts = {
unit: EtherUnit;
scaledValues?: string[];
};

export function useScaledWeiAmounts(arr?: number[], toUnit?: EtherUnit) {
return useMemo<ScaledWeiAmounts>(() => {
if (!arr) {
return {
unit: "wei",
};
}

const unit = toUnit ?? findBestUnit(Math.max(...arr));

return {
unit,
scaledValues: arr.map((item) => convertWei(item, unit)),
};
}, [arr, toUnit]);
}
22 changes: 9 additions & 13 deletions packages/eth-format/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
const ETH_UNITS = { wei: 0, Gwei: 9, ether: 18 };

export type EthAmount = string | number | bigint;
export type EtherUnit = keyof typeof ETH_UNITS;

const compactFormatter = Intl.NumberFormat("en-US", {
notation: "compact",
maximumFractionDigits: 2,
});

const fullwideFormatter = Intl.NumberFormat("fullwide", {
useGrouping: false,
});

/**
* This function converts `wei` to the unit specified by `toUnit`,
* adds commas to the integer part of the converted value,
Expand All @@ -15,10 +20,7 @@ const compactFormatter = Intl.NumberFormat("en-US", {
* This function never converts the provided value to a Number
* ensuring that the full precision of the input is preserved.
*/
export function formatWei(
wei: string | number | bigint,
toUnit: EtherUnit = "Gwei"
): string {
export function formatWei(wei: EthAmount, toUnit: EtherUnit = "Gwei"): string {
const converted = convertWei(wei, toUnit);
const formatted = insertCommas(converted);
return `${formatted} ${toUnit}`;
Expand All @@ -42,10 +44,7 @@ export function prettyFormatWei(
/**
* This function converts `wei` to the unit specified by `toUnit`.
*/
export function convertWei(
wei: string | number | bigint,
toUnit: EtherUnit = "Gwei"
): string {
export function convertWei(wei: EthAmount, toUnit: EtherUnit = "Gwei"): string {
return shiftDecimal(wei, ETH_UNITS[toUnit]);
}

Expand Down Expand Up @@ -74,7 +73,7 @@ export function countIntegerDigits(value: string | number | bigint): number {
return 0; // Return 0 for Infinity, -Infinity, and NaN
}

value = value.toString();
value = fullwideFormatter.format(value as Intl.StringNumericLiteral);

const negative = value.startsWith("-");

Expand All @@ -90,10 +89,7 @@ export function countIntegerDigits(value: string | number | bigint): number {
/**
* This function moves the decimal point to the left by `decimals` places.
*/
export function shiftDecimal(
value: string | number | bigint,
decimals: number
): string {
export function shiftDecimal(value: EthAmount, decimals: number): string {
value = value.toString();

const negative = value.startsWith("-");
Expand Down
32 changes: 30 additions & 2 deletions packages/eth-format/test/eth-units.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,35 @@ describe("countIntegerDigits", () => {
test("handles edge cases", () => {
expect(countIntegerDigits("0.0")).toBe(1);
expect(countIntegerDigits("-0.0")).toBe(1);
expect(countIntegerDigits(".123")).toBe(0);
expect(countIntegerDigits("-.123")).toBe(0);
expect(countIntegerDigits(".123")).toBe(1);
expect(countIntegerDigits("-.123")).toBe(1);
expect(countIntegerDigits("0.123")).toBe(1);
expect(countIntegerDigits("-0.123")).toBe(1);
});

test("scientific notation", () => {
expect(countIntegerDigits("1e+0")).toBe(1);
expect(countIntegerDigits("1e+1")).toBe(2);
expect(countIntegerDigits("1e+2")).toBe(3);

expect(countIntegerDigits("1e-0")).toBe(1);
expect(countIntegerDigits("1e-1")).toBe(1);
expect(countIntegerDigits("1e-2")).toBe(1);

expect(countIntegerDigits("1.23e+0")).toBe(1);
expect(countIntegerDigits("1.23e+1")).toBe(2);
expect(countIntegerDigits("1.23e+2")).toBe(3);

expect(countIntegerDigits("1.23e-0")).toBe(1);
expect(countIntegerDigits("1.23e-1")).toBe(1);
expect(countIntegerDigits("1.23e-2")).toBe(1);

expect(countIntegerDigits("1.23123123123123123123123e+0")).toBe(1);
expect(countIntegerDigits("1.23123123123123123123123e+1")).toBe(2);
expect(countIntegerDigits("1.23123123123123123123123e+2")).toBe(3);

expect(countIntegerDigits("1.23123123123123123123123e+10")).toBe(11);
expect(countIntegerDigits("1.23123123123123123123123e+100")).toBe(101);
expect(countIntegerDigits("1.23123123123123123123123e+200")).toBe(201);
});
});

0 comments on commit c9a6ada

Please sign in to comment.