From 58ab8c2ee740a4f8d51dfea03dee0de5486b5573 Mon Sep 17 00:00:00 2001 From: MananTank Date: Tue, 1 Apr 2025 18:12:49 +0000 Subject: [PATCH] [TOOL-3766] Dashboard: Account Abstraction page updates (#6609) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## PR-Codex overview This PR focuses on improving the UI and functionality of various components in the dashboard by modifying styles, enhancing layout elements, and integrating new features related to account abstraction and user operation statistics. ### Detailed summary - Removed `lg:gap-6` from grid classes in multiple components. - Increased header sizes from `text-lg` to `text-xl` in `SponsoredTransactionsTableUI.tsx`. - Adjusted margins and padding for improved spacing in various components. - Added new `GasCreditAlert` component for displaying gas credit information. - Integrated `AccountAbstractionSummary` into `AccountAbstractionAnalytics`. - Updated `userOpStats` handling in `Page` component to use promises for better performance. - Replaced certain text with more concise phrasing in descriptions. - Removed unused imports and optimized component structure for clarity. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` --- .../(team)/_components/TotalSponsoredCard.tsx | 4 +- .../billing/components/PlanInfoCard.tsx | 18 +-- .../SponsoredTransactionsTableUI.tsx | 2 +- .../~/usage/overview/components/UsageCard.tsx | 8 +- .../account-abstraction/AAFooterSection.tsx | 6 +- .../AccountAbstractionPage.tsx | 111 ++++++++++++------ .../connect/account-abstraction/isOpChain.ts | 3 - .../connect/account-abstraction/layout.tsx | 8 +- .../connect/account-abstraction/page.tsx | 25 +++- .../src/components/analytics/stat.tsx | 10 +- .../Analytics/InAppWalletUsersChartCard.tsx | 4 +- .../embedded-wallets/Analytics/Summary.tsx | 2 +- .../AccountAbstractionSummary.tsx | 2 +- .../SponsoredTransactionsChartCard.tsx | 22 +--- .../TotalSponsoredChartCard.tsx | 23 +--- .../AccountAbstractionAnalytics/index.tsx | 8 ++ 16 files changed, 133 insertions(+), 123 deletions(-) delete mode 100644 apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/isOpChain.ts diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/_components/TotalSponsoredCard.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/_components/TotalSponsoredCard.tsx index a1d4ad82730..d5c6b6fa82f 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/_components/TotalSponsoredCard.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/_components/TotalSponsoredCard.tsx @@ -88,10 +88,10 @@ export async function TotalSponsoredChartCardUI({ const filteredData = timeSeriesData.filter((d) => d.mainnet > 0); return (
-

+

{title || "Total Sponsored"}

-

{description}

+

{description}

-
+

{validPlan} Plan

@@ -56,6 +55,7 @@ export function PlanInfoCard(props: {
{/* go to invoices page */} + - )}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.tsx index 1c4c6c9469b..508f0365c5f 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/SponsoredTransactionsTableUI.tsx @@ -73,7 +73,7 @@ export function SponsoredTransactionsTableUI(
{/* header */}
-

Sponsored Transactions

+

Sponsored Transactions

{/* Filters */}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/UsageCard.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/UsageCard.tsx index 17413ea0628..94c53be64b0 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/UsageCard.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/usage/overview/components/UsageCard.tsx @@ -23,13 +23,13 @@ export const UsageCard: React.FC = ({ totalUsage, }) => { return ( -
-

{name}

-

{description}

+
+

{name}

+

{description}

-
+
{title &&

{title}

} {total !== undefined && ( diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/AAFooterSection.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/AAFooterSection.tsx index 7b253d316d1..e598ab027cc 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/AAFooterSection.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/AAFooterSection.tsx @@ -34,12 +34,12 @@ function FooterCard(props: { trackingCategory: string; }) { return ( -
-

+
+

{props.title}

-
+
{props.links.map((link) => ( -

+

Account Abstraction

- Easily integrate Account abstraction (ERC-4337) compliant smart accounts - into your apps.{" "} + Integrate ERC-4337 compliant smart accounts for gasless sponsorships and + more.
- View Documentation + Learn more about Account Abstraction

+
+
- {props.hasSmartWalletsWithoutBilling ? ( - - ) : ( - isOpChain && ( - - - - Using the gas credits for OP chain paymaster - - - Credits will automatically be applied to cover gas fees for any - onchain activity across thirdweb services.
- Eligible chains: OP Mainnet, Base, Zora, Frax, Mode. -
-
- ) - )} + {props.hasSmartWalletsWithoutBilling && } +
- - -
+
+
); } + +function GasCreditAlert(props: { + teamSlug: string; + projectId: string; +}) { + const [isVisible, setIsVisible] = useLocalStorage( + `gas-credit-${props.projectId}`, + true, + false, + ); + + if (!isVisible) return null; + + return ( +
+ +
+

OP Gas Credit Program

+

+ Redeem credits towards gas Sponsorship.
+ + Learn More + +

+ +
+ +
+
+
+ ); +} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/isOpChain.ts b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/isOpChain.ts deleted file mode 100644 index cd0dcc5c446..00000000000 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/isOpChain.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function isOpChainId(chainId: number) { - return [10, 8453, 7777777, 252, 34443].includes(chainId); -} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/layout.tsx index 8735c4ff358..fe0a90184bf 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/layout.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/layout.tsx @@ -1,4 +1,3 @@ -import { getAggregateUserOpUsage } from "@/api/analytics"; import { getProject } from "@/api/projects"; import { getTeamBySlug } from "@/api/team"; import type { Metadata } from "next"; @@ -34,18 +33,13 @@ export default async function Page(props: { team.billingStatus !== "validPayment" && team.billingStatus !== "pastDue"; - const userOpStats = await getAggregateUserOpUsage({ - teamId: team.id, - projectId: project.id, - }); - return ( {props.children} diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx index 63f59d1b133..c1c124ffc28 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/connect/account-abstraction/page.tsx @@ -1,5 +1,6 @@ -import { getUserOpUsage } from "@/api/analytics"; +import { getAggregateUserOpUsage, getUserOpUsage } from "@/api/analytics"; import { getProject } from "@/api/projects"; +import { getTeamBySlug } from "@/api/team"; import { getThirdwebClient } from "@/constants/thirdweb.server"; import { type Range, @@ -31,7 +32,14 @@ export default async function Page(props: { notFound(); } - const project = await getProject(params.team_slug, params.project_slug); + const [team, project] = await Promise.all([ + getTeamBySlug(params.team_slug), + getProject(params.team_slug, params.project_slug), + ]); + + if (!team) { + redirect("/team"); + } if (!project) { redirect(`/team/${params.team_slug}`); @@ -52,7 +60,7 @@ export default async function Page(props: { type: rangeType, }; - const userOpStats = await getUserOpUsage({ + const userOpStatsPromise = getUserOpUsage({ teamId: project.teamId, projectId: project.id, from: range.from, @@ -60,6 +68,16 @@ export default async function Page(props: { period: interval, }); + const aggregateUserOpStatsPromise = getAggregateUserOpUsage({ + teamId: team.id, + projectId: project.id, + }); + + const [userOpStats, aggregateUserOpStats] = await Promise.all([ + userOpStatsPromise, + aggregateUserOpStatsPromise, + ]); + return ( ); } diff --git a/apps/dashboard/src/components/analytics/stat.tsx b/apps/dashboard/src/components/analytics/stat.tsx index cee00c8145f..0e29ee0dda6 100644 --- a/apps/dashboard/src/components/analytics/stat.tsx +++ b/apps/dashboard/src/components/analytics/stat.tsx @@ -5,18 +5,16 @@ export const Stat: React.FC<{ formatter?: (value: number) => string; }> = ({ label, value, formatter, icon: Icon }) => { return ( -
+
-
+
{value !== undefined && formatter ? formatter(value) : value?.toLocaleString()}
-
- {label} -
+
{label}
- +
); }; diff --git a/apps/dashboard/src/components/embedded-wallets/Analytics/InAppWalletUsersChartCard.tsx b/apps/dashboard/src/components/embedded-wallets/Analytics/InAppWalletUsersChartCard.tsx index 8728f1f502a..26d55aa0ffb 100644 --- a/apps/dashboard/src/components/embedded-wallets/Analytics/InAppWalletUsersChartCard.tsx +++ b/apps/dashboard/src/components/embedded-wallets/Analytics/InAppWalletUsersChartCard.tsx @@ -115,10 +115,10 @@ export function InAppWalletUsersChartCardUI(props: { return (
-

+

{props.title}

-

{props.description}

+

{props.description}

+
+
-

+

Sponsored Transactions

- Total number of sponsored transactions. + Total number of sponsored transactions

@@ -139,7 +139,7 @@ export function SponsoredTransactionsChartCard(props: {
{/* Chart */} - + {props.isPending ? ( ) : chartData.length === 0 || @@ -164,18 +164,6 @@ export function SponsoredTransactionsChartCard(props: { axisLine={false} /> - { - return Object.entries(data) - .filter(([key]) => key !== "time") - .map(([, value]) => value) - .reduce((acc, current) => Number(acc) + Number(current), 0); - }} - tickLine={false} - axisLine={false} - tickFormatter={(value) => formatTickerNumber(value)} - /> - - + Send your first sponsored transaction
diff --git a/apps/dashboard/src/components/smart-wallets/AccountAbstractionAnalytics/TotalSponsoredChartCard.tsx b/apps/dashboard/src/components/smart-wallets/AccountAbstractionAnalytics/TotalSponsoredChartCard.tsx index 5f136a00318..b80cdf1cd7d 100644 --- a/apps/dashboard/src/components/smart-wallets/AccountAbstractionAnalytics/TotalSponsoredChartCard.tsx +++ b/apps/dashboard/src/components/smart-wallets/AccountAbstractionAnalytics/TotalSponsoredChartCard.tsx @@ -21,7 +21,7 @@ import { UnrealIcon } from "components/icons/brand-icons/UnrealIcon"; import { DocLink } from "components/shared/DocLink"; import { format } from "date-fns"; import { useMemo } from "react"; -import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"; +import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"; import type { UserOpStats } from "types/analytics"; import { useAllChainsData } from "../../../hooks/chains/allChains"; import { toUSD } from "../../../utils/number"; @@ -111,11 +111,11 @@ export function TotalSponsoredChartCard(props: { return (
-

+

Gas Sponsored

- The total amount of gas sponsored in USD. + The total amount of gas sponsored in USD

@@ -139,10 +139,7 @@ export function TotalSponsoredChartCard(props: {
{/* Chart */} - + {props.isPending ? ( ) : chartData.length === 0 || @@ -201,18 +198,6 @@ export function TotalSponsoredChartCard(props: { axisLine={false} /> - { - return Object.entries(data) - .filter(([key]) => key !== "time") - .map(([, value]) => value) - .reduce((acc, current) => Number(acc) + Number(current), 0); - }} - tickLine={false} - axisLine={false} - tickFormatter={(value) => toUSD(value)} - /> - + + +
+