diff --git a/explorer/src/components/StatsCard.tsx b/explorer/src/components/StatsCard.tsx
index 0e901c576d..aa9ae74882 100644
--- a/explorer/src/components/StatsCard.tsx
+++ b/explorer/src/components/StatsCard.tsx
@@ -8,6 +8,7 @@ import {
useRootSlot,
PERF_UPDATE_SEC,
useSetActive,
+ PerformanceInfo,
} from "providers/stats/solanaBeach";
import { slotsToHumanString } from "utils";
import { useCluster, Cluster } from "providers/cluster";
@@ -31,8 +32,6 @@ function StatsCardBody() {
const rootSlot = useRootSlot();
const dashboardInfo = useDashboardInfo();
const performanceInfo = usePerformanceInfo();
- const txTrackerRef = React.useRef({ old: 0, new: 0 });
- const txTracker = txTrackerRef.current;
const setSocketActive = useSetActive();
const { cluster } = useCluster();
@@ -53,20 +52,6 @@ function StatsCardBody() {
);
}
- if (performanceInfo) {
- const { totalTransactionCount: txCount, avgTPS } = performanceInfo;
-
- // Track last tx count to initialize count up
- if (txCount !== txTracker.new) {
- // If this is the first tx count value, estimate the previous one
- // in order to have a starting point for our animation
- txTracker.old = txTracker.new || txCount - PERF_UPDATE_SEC * avgTPS;
- txTracker.new = txCount;
- }
- } else {
- txTrackerRef.current = { old: 0, new: 0 };
- }
-
if (rootSlot === undefined || !dashboardInfo || !performanceInfo) {
return (
@@ -83,18 +68,8 @@ function StatsCardBody() {
const currentEpoch = epochInfo.epoch.toString();
const epochProgress = ((100 * slotIndex) / slotsInEpoch).toFixed(1) + "%";
const epochTimeRemaining = slotsToHumanString(slotsInEpoch - slotIndex);
- const transactionCount = (
-
- );
const averageTps = Math.round(performanceInfo.avgTPS);
+ const transactionCount =
;
return (
@@ -129,3 +104,45 @@ function StatsCardBody() {
);
}
+
+function AnimatedTransactionCount({ info }: { info: PerformanceInfo }) {
+ const txCountRef = React.useRef(0);
+ const countUpRef = React.useRef({ start: 0, period: 0, lastUpdate: 0 });
+ const countUp = countUpRef.current;
+
+ const { totalTransactionCount: txCount, avgTPS } = info;
+
+ // Track last tx count to reset count up options
+ if (txCount !== txCountRef.current) {
+ if (countUp.lastUpdate > 0) {
+ // Since we overshoot below, calculate the elapsed value
+ // and start from there.
+ const elapsed = Date.now() - countUp.lastUpdate;
+ const elapsedPeriods = elapsed / (PERF_UPDATE_SEC * 1000);
+ countUp.start = countUp.start + elapsedPeriods * countUp.period;
+ countUp.period = txCount - countUp.start;
+ } else {
+ // Since this is the first tx count value, estimate the previous
+ // tx count in order to have a starting point for our animation
+ countUp.period = PERF_UPDATE_SEC * avgTPS;
+ countUp.start = txCount - countUp.period;
+ }
+ countUp.lastUpdate = Date.now();
+ txCountRef.current = txCount;
+ }
+
+ // Overshoot the target tx count in case the next update is delayed
+ const COUNT_PERIODS = 3;
+ const countUpEnd = countUp.start + COUNT_PERIODS * countUp.period;
+ return (
+
+ );
+}
diff --git a/explorer/src/providers/stats/solanaBeach.tsx b/explorer/src/providers/stats/solanaBeach.tsx
index fab0d068c0..cd76469243 100644
--- a/explorer/src/providers/stats/solanaBeach.tsx
+++ b/explorer/src/providers/stats/solanaBeach.tsx
@@ -74,7 +74,7 @@ const DashboardContext = React.createContext
(
undefined
);
-type PerformanceInfo = StructType;
+export type PerformanceInfo = StructType;
type PerformanceState = { info: PerformanceInfo | undefined };
const PerformanceContext = React.createContext(
undefined