Skip to content

Commit f3d2739

Browse files
authored
Improve relayer analytics (#8533)
1 parent 1aa4912 commit f3d2739

File tree

4 files changed

+59
-31
lines changed

4 files changed

+59
-31
lines changed

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/dedicated-relayer/components/active-state.tsx

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { ExternalLinkIcon, XIcon } from "lucide-react";
55
import Link from "next/link";
66
import { useState } from "react";
77
import type { ThirdwebClient } from "thirdweb";
8+
import {
9+
DateRangeSelector,
10+
type Range,
11+
} from "@/components/analytics/date-range-selector";
812
import { SingleNetworkSelector } from "@/components/blocks/NetworkSelectors";
913
import { PaginationButtons } from "@/components/blocks/pagination-buttons";
1014
import { WalletAddress } from "@/components/blocks/wallet-address";
@@ -35,15 +39,15 @@ type DedicatedRelayerActiveStateProps = {
3539
teamId: string;
3640
fleetId: string;
3741
client: ThirdwebClient;
38-
from: string;
39-
to: string;
42+
range: Range;
43+
setRange: (range: Range) => void;
4044
className?: string;
4145
};
4246

4347
export function DedicatedRelayerActiveState(
4448
props: DedicatedRelayerActiveStateProps,
4549
) {
46-
const { fleet, teamId, fleetId, client, from, to } = props;
50+
const { fleet, teamId, fleetId, client, range, setRange } = props;
4751

4852
const pageSize = 10;
4953
const [page, setPage] = useState(1);
@@ -52,15 +56,15 @@ export function DedicatedRelayerActiveState(
5256
const summaryQuery = useFleetTransactionsSummary({
5357
teamId,
5458
fleetId,
55-
from,
56-
to,
59+
from: range.from.toISOString(),
60+
to: range.to.toISOString(),
5761
});
5862

5963
const transactionsQuery = useFleetTransactions({
6064
teamId,
6165
fleetId,
62-
from,
63-
to,
66+
from: range.from.toISOString(),
67+
to: range.to.toISOString(),
6468
limit: pageSize,
6569
offset: (page - 1) * pageSize,
6670
chainId: chainIdFilter,
@@ -70,8 +74,18 @@ export function DedicatedRelayerActiveState(
7074
? Math.ceil(transactionsQuery.data.meta.total / pageSize)
7175
: 0;
7276

77+
// Filter active chains to only include those in the fleet
78+
const activeChainsCount =
79+
summaryQuery.data?.data.transactionsByChain.filter((c) =>
80+
fleet.chainIds.includes(Number(c.chainId)),
81+
).length ?? 0;
82+
7383
return (
7484
<div className={cn("flex flex-col gap-6", props.className)}>
85+
<div className="flex justify-end">
86+
<DateRangeSelector range={range} setRange={setRange} />
87+
</div>
88+
7589
{/* Summary Stats */}
7690
<div className="grid gap-4 md:grid-cols-3">
7791
<StatCard
@@ -92,9 +106,7 @@ export function DedicatedRelayerActiveState(
92106
/>
93107
<StatCard
94108
title="Active Chains"
95-
value={
96-
summaryQuery.data?.data.transactionsByChain.length.toString() ?? "—"
97-
}
109+
value={summaryQuery.data ? activeChainsCount.toString() : "—"}
98110
isLoading={summaryQuery.isPending}
99111
/>
100112
</div>
@@ -132,6 +144,7 @@ export function DedicatedRelayerActiveState(
132144
setPage(1);
133145
}}
134146
client={client}
147+
chainIds={fleet.chainIds}
135148
/>
136149
</div>
137150
</div>
@@ -143,7 +156,6 @@ export function DedicatedRelayerActiveState(
143156
<TableHead>Transaction Hash</TableHead>
144157
<TableHead>Chain</TableHead>
145158
<TableHead>Wallet</TableHead>
146-
<TableHead>Executor</TableHead>
147159
<TableHead>Timestamp</TableHead>
148160
<TableHead>Fee</TableHead>
149161
</TableRow>
@@ -244,9 +256,6 @@ function TransactionRow(props: {
244256
<TableCell>
245257
<WalletAddress address={transaction.walletAddress} client={client} />
246258
</TableCell>
247-
<TableCell>
248-
<WalletAddress address={transaction.executorAddress} client={client} />
249-
</TableCell>
250259
<TableCell>
251260
<ToolTipLabel hoverable label={format(new Date(utcTimestamp), "PPpp")}>
252261
<span>
@@ -275,9 +284,6 @@ function SkeletonRow() {
275284
<TableCell>
276285
<Skeleton className="h-7 w-[130px]" />
277286
</TableCell>
278-
<TableCell>
279-
<Skeleton className="h-7 w-[130px]" />
280-
</TableCell>
281287
<TableCell>
282288
<Skeleton className="h-7 w-[80px]" />
283289
</TableCell>
@@ -350,7 +356,10 @@ function ChainCell(props: { chainId: string; client: ThirdwebClient }) {
350356
);
351357
}
352358

353-
function TransactionFeeCell(props: { usdValue: number }) {
359+
function TransactionFeeCell(props: { usdValue: number | null }) {
360+
if (props.usdValue === null) {
361+
return <span className="font-mono text-sm text-muted-foreground"></span>;
362+
}
354363
return (
355364
<span className="font-mono text-sm">
356365
${props.usdValue < 0.01 ? "<0.01" : props.usdValue.toFixed(2)}
@@ -362,6 +371,7 @@ function ChainFilter(props: {
362371
chainId: number | undefined;
363372
setChainId: (chainId: number | undefined) => void;
364373
client: ThirdwebClient;
374+
chainIds: number[];
365375
}) {
366376
return (
367377
<div className="flex bg-background">
@@ -373,6 +383,7 @@ function ChainFilter(props: {
373383
align="end"
374384
placeholder="All Chains"
375385
className="min-w-[150px]"
386+
chainIds={props.chainIds}
376387
/>
377388
</div>
378389
);

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/dedicated-relayer/components/page-client.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"use client";
22

3-
import { useEffect, useState } from "react";
3+
import { subDays } from "date-fns";
4+
import { useEffect, useMemo, useState } from "react";
45
import type { ThirdwebClient } from "thirdweb";
6+
import type { Range } from "@/components/analytics/date-range-selector";
57
import type { DedicatedRelayerSKU } from "@/types/billing";
68
import { getAbsoluteUrl } from "@/utils/vercel";
79
import { useFleetStatus, useFleetTransactionsSummary } from "../lib/hooks";
@@ -19,6 +21,7 @@ type DedicatedRelayerPageClientProps = {
1921
fleetId: string;
2022
from: string;
2123
to: string;
24+
rangeType: Range["type"];
2225
initialFleet: Fleet | null;
2326
};
2427

@@ -30,6 +33,12 @@ export function DedicatedRelayerPageClient(
3033
getInitialStatus(props.initialFleet),
3134
);
3235

36+
const [dateRange, setDateRange] = useState<Range>({
37+
from: new Date(props.from),
38+
to: new Date(props.to),
39+
type: props.rangeType,
40+
});
41+
3342
// Poll for fleet status when not purchased or pending setup
3443
const fleetStatusQuery = useFleetStatus(
3544
props.teamSlug,
@@ -45,17 +54,26 @@ export function DedicatedRelayerPageClient(
4554
}
4655
}, [fleetStatusQuery.data]);
4756

48-
// Only fetch transactions summary when we have an active fleet with executors
49-
const summaryQuery = useFleetTransactionsSummary({
57+
const activityWindowDates = useMemo(() => {
58+
const now = new Date();
59+
return {
60+
from: subDays(now, 120).toISOString(),
61+
to: now.toISOString(),
62+
};
63+
}, []);
64+
65+
// Check for any activity in the last 120 days to determine if we should show the dashboard
66+
// This prevents switching back to "pending" state if the user selects a date range with no transactions
67+
const hasActivityQuery = useFleetTransactionsSummary({
5068
teamId: props.teamId,
5169
fleetId: props.fleetId,
52-
from: props.from,
53-
to: props.to,
70+
from: activityWindowDates.from,
71+
to: activityWindowDates.to,
5472
enabled: fleetStatus === "active",
5573
refetchInterval: 5000,
5674
});
5775

58-
const totalTransactions = summaryQuery.data?.data.totalTransactions ?? 0;
76+
const totalTransactions = hasActivityQuery.data?.data.totalTransactions ?? 0;
5977
const hasTransactions = totalTransactions > 0;
6078

6179
// TODO-FLEET: Implement purchase flow
@@ -112,8 +130,8 @@ export function DedicatedRelayerPageClient(
112130
teamId={props.teamId}
113131
fleetId={props.fleetId}
114132
client={props.client}
115-
from={props.from}
116-
to={props.to}
133+
range={dateRange}
134+
setRange={setDateRange}
117135
/>
118136
)}
119137
</div>

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/dedicated-relayer/page.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ export default async function DedicatedRelayerPage(props: {
4242
// Build fleet ID from team and project
4343
const fleetId = buildFleetId(team.id, project.id);
4444

45-
// Default date range: last 30 days
46-
const range = getLastNDaysRange("last-30");
45+
// Default date range: last 7 days
46+
const range = getLastNDaysRange("last-7");
4747

4848
// Extract fleet configuration from bundler service
4949
const bundlerService = project.services.find((s) => s.name === "bundler");
@@ -79,6 +79,7 @@ export default async function DedicatedRelayerPage(props: {
7979
fleetId={fleetId}
8080
from={range.from.toISOString()}
8181
to={range.to.toISOString()}
82+
rangeType={range.type}
8283
initialFleet={initialFleet}
8384
/>
8485
);

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/dedicated-relayer/types.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ export type FleetTransaction = {
3333
timestamp: string;
3434
chainId: string;
3535
transactionFee: number;
36-
transactionFeeUsd: number;
36+
transactionFeeUsd: number | null;
3737
walletAddress: string;
3838
transactionHash: string;
39-
userOpHash: string;
40-
executorAddress: string;
4139
};
4240

4341
/**

0 commit comments

Comments
 (0)