Skip to content

Commit cda0adf

Browse files
transaction chart
1 parent 8477ea7 commit cda0adf

File tree

4 files changed

+98
-14
lines changed

4 files changed

+98
-14
lines changed

apps/dashboard/src/app/team/[team_slug]/[project_slug]/transactions/analytics/analytics-page.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ export function TransactionsAnalyticsPageContent(props: {
2020
</div>
2121
<div className="h-6" />
2222
<div className="flex grow flex-col gap-6">
23-
<TransactionsChartCard searchParams={props.searchParams} />
23+
<TransactionsChartCard
24+
searchParams={props.searchParams}
25+
teamId={props.teamId}
26+
clientId={props.clientId}
27+
/>
2428
<TransactionsTable teamId={props.teamId} clientId={props.clientId} />
2529
</div>
2630
</div>

apps/dashboard/src/app/team/[team_slug]/[project_slug]/transactions/analytics/tx-chart/tx-chart-ui.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { DocLink } from "components/shared/DocLink";
1212
import { formatDate } from "date-fns";
1313
import { useAllChainsData } from "hooks/chains/allChains";
1414
import { useMemo } from "react";
15-
import type { UserOpStats } from "types/analytics";
15+
import type { TransactionStats } from "types/analytics";
1616
import { formatTickerNumber } from "../../../../../../../lib/format-utils";
1717

1818
type ChartData = Record<string, number> & {
@@ -25,7 +25,7 @@ type ChartData = Record<string, number> & {
2525
// TODO - update the name of the component to something more relevant
2626
export function TransactionsChartCardUI(props: {
2727
// TODO - update this
28-
userOpStats: UserOpStats[];
28+
userOpStats: TransactionStats[];
2929
isPending: boolean;
3030
}) {
3131
const { userOpStats } = props;
@@ -43,20 +43,20 @@ export function TransactionsChartCardUI(props: {
4343
const { chainId } = stat;
4444
const chain = chainsStore.idToChain.get(Number(chainId));
4545

46-
const chainName = chain?.name || chainId || "Unknown";
46+
const chainName = chain?.name || chainId.toString() || "Unknown";
4747
// if no data for current day - create new entry
4848
if (!chartData) {
4949
_chartDataMap.set(stat.date, {
5050
time: stat.date,
51-
[chainName]: stat.successful,
51+
[chainName]: stat.count,
5252
} as ChartData);
5353
} else {
54-
chartData[chainName] = (chartData[chainName] || 0) + stat.successful;
54+
chartData[chainName] = (chartData[chainName] || 0) + stat.count;
5555
}
5656

5757
chainIdToVolumeMap.set(
5858
chainName,
59-
stat.successful + (chainIdToVolumeMap.get(chainName) || 0),
59+
stat.count + (chainIdToVolumeMap.get(chainName) || 0),
6060
);
6161
}
6262

@@ -108,10 +108,10 @@ export function TransactionsChartCardUI(props: {
108108
customHeader={
109109
<div className="relative px-6 pt-6">
110110
<h3 className="mb-0.5 font-semibold text-xl tracking-tight">
111-
Lorem Ipsum
111+
Daily Transactions
112112
</h3>
113113
<p className="text-muted-foreground text-sm">
114-
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
114+
Amount of daily transactions by chain.
115115
</p>
116116

117117
<div className="top-6 right-6 mb-8 grid grid-cols-2 items-center gap-2 md:absolute md:mb-0 md:flex">

apps/dashboard/src/app/team/[team_slug]/[project_slug]/transactions/analytics/tx-chart/tx-chart.tsx

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
import { differenceInDays } from "date-fns";
22
import { ResponsiveSuspense } from "responsive-rsc";
3-
import type { UserOpStats } from "../../../../../../../types/analytics";
3+
import { THIRDWEB_ENGINE_CLOUD_URL } from "../../../../../../../@/constants/env";
4+
import type {
5+
TransactionStats,
6+
UserOpStats,
7+
} from "../../../../../../../types/analytics";
8+
import { getAuthToken } from "../../../../../../api/lib/getAuthToken";
49
import { getTxAnalyticsFiltersFromSearchParams } from "../getTransactionAnalyticsFilter";
510
import { TransactionsChartCardUI } from "./tx-chart-ui";
611

712
async function AsyncTransactionsChartCard(props: {
813
from: string;
914
to: string;
1015
interval: "day" | "week";
16+
teamId: string;
17+
clientId: string;
1118
}) {
12-
// TODO - remove stub, implement it
13-
await new Promise((resolve) => setTimeout(resolve, 1000));
14-
const data = getTransactionChartStub(props.from, props.to, props.interval);
19+
const data = await getTransactionsChart({
20+
teamId: props.teamId,
21+
clientId: props.clientId,
22+
from: props.from,
23+
to: props.to,
24+
interval: props.interval,
25+
});
1526

1627
return <TransactionsChartCardUI isPending={false} userOpStats={data} />;
1728
}
@@ -22,6 +33,8 @@ export function TransactionsChartCard(props: {
2233
to?: string | undefined | string[];
2334
interval?: string | undefined | string[];
2435
};
36+
teamId: string;
37+
clientId: string;
2538
}) {
2639
const { range, interval } = getTxAnalyticsFiltersFromSearchParams(
2740
props.searchParams,
@@ -37,6 +50,8 @@ export function TransactionsChartCard(props: {
3750
from={range.from.toISOString()}
3851
to={range.to.toISOString()}
3952
interval={interval}
53+
teamId={props.teamId}
54+
clientId={props.clientId}
4055
/>
4156
</ResponsiveSuspense>
4257
);
@@ -76,3 +91,68 @@ function getTransactionChartStub(
7691

7792
return stub;
7893
}
94+
95+
async function getTransactionsChart({
96+
teamId,
97+
clientId,
98+
from,
99+
to,
100+
interval,
101+
}: {
102+
teamId: string;
103+
clientId: string;
104+
from: string;
105+
to: string;
106+
interval: "day" | "week";
107+
}): Promise<TransactionStats[]> {
108+
const authToken = await getAuthToken();
109+
110+
const filters = {
111+
startDate: from,
112+
endDate: to,
113+
resolution: interval,
114+
};
115+
116+
const response = await fetch(
117+
`${THIRDWEB_ENGINE_CLOUD_URL}/project/transactions/analytics`,
118+
{
119+
method: "POST",
120+
headers: {
121+
"Content-Type": "application/json",
122+
"x-team-id": teamId,
123+
"x-client-id": clientId,
124+
Authorization: `Bearer ${authToken}`,
125+
},
126+
body: JSON.stringify(filters),
127+
},
128+
);
129+
130+
if (!response.ok) {
131+
throw new Error(
132+
`Error fetching transactions chart data: ${response.status} ${response.statusText}`,
133+
);
134+
}
135+
136+
type TransactionsChartResponse = {
137+
result: {
138+
analytics: Array<{
139+
timeBucket: string;
140+
chainId: string;
141+
count: number;
142+
}>;
143+
metadata: {
144+
resolution: string;
145+
startDate: string;
146+
endDate: string;
147+
};
148+
};
149+
};
150+
151+
const data = (await response.json()) as TransactionsChartResponse;
152+
153+
return data.result.analytics.map((stat) => ({
154+
date: stat.timeBucket,
155+
chainId: Number(stat.chainId),
156+
count: stat.count,
157+
}));
158+
}

apps/dashboard/src/components/analytics/date-range-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export function getLastNDaysRange(id: DurationId) {
8383
throw new Error("Invalid duration id");
8484
}
8585

86-
const todayDate = new Date();
86+
const todayDate = new Date(Date.now() + 1000 * 60 * 60 * 24); // add 1 day to avoid timezone issues
8787

8888
const value: Range = {
8989
type: id,

0 commit comments

Comments
 (0)