Skip to content

Dashboard: Move account-abstraction page #7379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 46 additions & 9 deletions apps/dashboard/redirects.js
Original file line number Diff line number Diff line change
@@ -62,6 +62,51 @@ const legacyDashboardToTeamRedirects = [
},
];

const projectRoute = "/team/:team_slug/:project_slug";

const projectPageRedirects = [
{
source: `${projectRoute}/connect/pay/:path*`,
destination: `${projectRoute}/universal-bridge/:path*`,
permanent: false,
},
{
source: `${projectRoute}/connect/universal-bridge/:path*`,
destination: `${projectRoute}/universal-bridge/:path*`,
permanent: false,
},
{
source: `${projectRoute}/connect/account-abstraction/:path*`,
destination: `${projectRoute}/account-abstraction/:path*`,
permanent: false,
},
{
source: `${projectRoute}/connect/in-app-wallets/:path*`,
destination: `${projectRoute}/wallets/:path*`,
permanent: false,
},
{
source: `${projectRoute}/engine/cloud/vault/:path*`,
destination: `${projectRoute}/vault/:path*`,
permanent: false,
},
{
source: `${projectRoute}/engine/cloud/:path*`,
destination: `${projectRoute}/transactions/:path*`,
permanent: false,
},
{
source: `${projectRoute}/assets/:path*`,
destination: `${projectRoute}/tokens/:path*`,
permanent: false,
},
{
source: `${projectRoute}/nebula/:path*`,
destination: projectRoute,
permanent: false,
},
];

/** @type {import('next').NextConfig['redirects']} */
async function redirects() {
return [
@@ -326,14 +371,6 @@ async function redirects() {
destination: "/",
permanent: false,
},
// pay > universal-bridge redirect
{
source: "/team/:team_slug/:project_slug/connect/pay/:path*",
destination:
"/team/:team_slug/:project_slug/connect/universal-bridge/:path*",
permanent: false,
},

// all /learn/tutorials (and sub-routes) -> /learn/guides
{
source: "/learn/tutorials/:path*",
@@ -382,8 +419,8 @@ async function redirects() {
destination: "/transactions",
permanent: false,
},

...legacyDashboardToTeamRedirects,
...projectPageRedirects,
];
}

6 changes: 3 additions & 3 deletions apps/dashboard/src/@/analytics/report.ts
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ import type { Team } from "../api/team";
* ### Why do we need to report this event?
* - To track the number of contracts deployed
* - To track the number of contracts deployed on each chain
* - To track if the contract was deployed on the asset page vs on the deploy page
* - To track if the contract was deployed on the token page vs on the deploy page
*
* ### Who is responsible for this event?
* @jnsdls
@@ -230,7 +230,7 @@ type AssetContractType = "DropERC20" | "DropERC1155" | "DropERC721";

/**
* ### Why do we need to report this event?
* - To track number of successful asset purchases from the asset page
* - To track number of successful asset purchases from the token page
* - To track which asset and contract types are being purchased the most
*
* ### Who is responsible for this event?
@@ -250,7 +250,7 @@ export function reportAssetBuySuccessful(properties: {

/**
* ### Why do we need to report this event?
* - To track number of failed asset purchases from the asset page
* - To track number of failed asset purchases from the token page
* - To track the errors that users encounter when trying to purchase an asset
*
* ### Who is responsible for this event?
1 change: 1 addition & 0 deletions apps/dashboard/src/@/components/blocks/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ export type SidebarBaseLink = {
label: React.ReactNode;
exactMatch?: boolean;
icon?: React.FC<{ className?: string }>;
isActive?: (pathname: string) => boolean;
};

export type SidebarLink =
1 change: 1 addition & 0 deletions apps/dashboard/src/@/components/blocks/SidebarLayout.tsx
Original file line number Diff line number Diff line change
@@ -123,6 +123,7 @@ function RenderSidebarGroup(props: {
className="flex items-center gap-2 text-muted-foreground text-sm hover:bg-accent"
activeClassName="text-foreground bg-accent"
exactMatch={link.exactMatch}
isActive={link.isActive}
onClick={() => {
sidebar.setOpenMobile(false);
}}
13 changes: 8 additions & 5 deletions apps/dashboard/src/@/components/ui/NavLink.tsx
Original file line number Diff line number Diff line change
@@ -11,15 +11,18 @@ export type NavButtonProps = {
href: string;
exactMatch?: boolean;
onClick?: () => void;
isActive?: (pathname: string) => boolean;
};

export function NavLink(props: React.PropsWithChildren<NavButtonProps>) {
const pathname = usePathname();
const isActive = pathname
? props.exactMatch
? pathname === props.href
: pathname.startsWith(props.href)
: false;
const isActive = props.isActive
? props.isActive(pathname)
: pathname
? props.exactMatch
? pathname === props.href
: pathname.startsWith(props.href)
: false;
return (
<Link
href={props.href}
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ export const PrimaryDashboardButton: React.FC<AddToDashboardCardProps> = ({
rel="noopener noreferrer"
className="gap-2"
>
View Asset Page <ExternalLinkIcon className="size-3.5" />
View Token Page <ExternalLinkIcon className="size-3.5" />
</Link>
</Button>
);
Original file line number Diff line number Diff line change
@@ -45,10 +45,10 @@ export const ContractOverviewPage: React.FC<ContractOverviewPageProps> = ({
<div className="flex grow flex-col gap-10 overflow-hidden">
{isErc20 && (
<UpsellBannerCard
title="Public asset page available"
description="A public page is available for this contract for anyone to buy this asset"
title="Public token page available"
description="A public page is available for this contract for anyone to buy this token"
cta={{
text: "View asset page",
text: "View token page",
icon: <ExternalLinkIcon className="size-4" />,
target: "_blank",
link: `/${chainSlug}/${contract.address}`,
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ export function DeployedContractsPageHeader(props: {
const [importModalOpen, setImportModalOpen] = useState(false);

return (
<div className="border-b">
<div>
<ImportModal
client={props.client}
isOpen={importModalOpen}
@@ -28,24 +28,28 @@ export function DeployedContractsPageHeader(props: {
type="contract"
/>

<div className="container flex max-w-7xl flex-col gap-3 py-10 lg:flex-row lg:items-center lg:justify-between">
<div className="container flex max-w-7xl flex-col gap-3 pt-10 pb-5 lg:flex-row lg:items-center lg:justify-between">
<div>
<h1 className="font-semibold text-2xl tracking-tight lg:text-3xl">
Contracts
</h1>
<p className="text-muted-foreground">
Deploy and manage contracts for your project
</p>
</div>
<div className="flex gap-3 [&>*]:grow">
<Button
className="gap-2 bg-card"
className="gap-1.5 bg-card"
size="sm"
variant="outline"
onClick={() => {
setImportModalOpen(true);
}}
>
<DownloadIcon className="size-4" />
<DownloadIcon className="size-4 text-muted-foreground" />
Import contract
</Button>
<Button asChild className="gap-2">
<Button asChild className="gap-1.5" size="sm">
<Link href="/explore">
<PlusIcon className="size-4" />
Deploy contract
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ import { Spinner } from "@/components/ui/Spinner/Spinner";
import { ContractTable } from "components/contract-components/tables/contract-table";
import { Suspense } from "react";
import type { ThirdwebClient } from "thirdweb";
import { DeployedContractsPageHeader } from "../DeployedContractsPageHeader";
import { DeployViaCLIOrImportCard } from "./DeployViaCLIOrImportCard";
import { getSortedDeployedContracts } from "./getSortedDeployedContracts";

@@ -16,24 +15,16 @@ export function DeployedContractsPage(props: {
projectSlug: string;
}) {
return (
<div className="flex grow flex-col">
<DeployedContractsPageHeader
<div className="container flex max-w-7xl grow flex-col">
<Suspense fallback={<Loading />}>
<DeployedContractsPageAsync {...props} />
</Suspense>
<div className="h-8" />
<DeployViaCLIOrImportCard
client={props.client}
teamId={props.teamId}
projectId={props.projectId}
client={props.client}
/>
<div className="h-6" />
<div className="container flex max-w-7xl grow flex-col">
<Suspense fallback={<Loading />}>
<DeployedContractsPageAsync {...props} />
</Suspense>
<div className="h-8" />
<DeployViaCLIOrImportCard
client={props.client}
teamId={props.teamId}
projectId={props.projectId}
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FooterLinksSection } from "../../components/footer/FooterLinksSection";
import { FooterLinksSection } from "../components/footer/FooterLinksSection";

export function AAFooter() {
return (
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ export function AccountAbstractionLayout(props: {
children: React.ReactNode;
hasSmartWalletsWithoutBilling: boolean;
}) {
const smartWalletsLayoutSlug = `/team/${props.teamSlug}/${props.projectSlug}/connect/account-abstraction`;
const smartWalletsLayoutSlug = `/team/${props.teamSlug}/${props.projectSlug}/account-abstraction`;

return (
<div className="flex grow flex-col">
Original file line number Diff line number Diff line change
@@ -6,6 +6,9 @@ import { UnderlineLink } from "@/components/ui/UnderlineLink";
import { Button } from "@/components/ui/button";
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
import { serverThirdwebClient } from "@/constants/thirdweb-client.server";
import { getSortedDeployedContracts } from "@app/account/contracts/_components/getSortedDeployedContracts";
import { getAuthToken } from "@app/api/lib/getAuthToken";
import { loginRedirect } from "@app/login/loginRedirect";
import { DefaultFactoriesSection } from "components/smart-wallets/AccountFactories";
import { FactoryContracts } from "components/smart-wallets/AccountFactories/factory-contracts";
import { PlusIcon } from "lucide-react";
@@ -14,9 +17,6 @@ import { redirect } from "next/navigation";
import { Suspense } from "react";
import { type ThirdwebClient, defineChain, getContract } from "thirdweb";
import { getCompilerMetadata } from "thirdweb/contract";
import { getSortedDeployedContracts } from "../../../../../../../account/contracts/_components/getSortedDeployedContracts";
import { getAuthToken } from "../../../../../../../api/lib/getAuthToken";
import { loginRedirect } from "../../../../../../../login/loginRedirect";

export default async function Page(props: {
params: Promise<{ team_slug: string; project_slug: string }>;
@@ -31,7 +31,7 @@ export default async function Page(props: {

if (!authToken) {
loginRedirect(
`/team/${params.team_slug}/${params.project_slug}/connect/account-abstraction/factories`,
`/team/${params.team_slug}/${params.project_slug}/account-abstraction/factories`,
);
}

Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { getUserOpUsage } from "@/api/analytics";
import { getProject } from "@/api/projects";
import { getTeamBySlug } from "@/api/team";
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
import { getAuthToken } from "@app/api/lib/getAuthToken";
import {
type Range,
getLastNDaysRange,
@@ -10,7 +11,6 @@ import { AccountAbstractionAnalytics } from "components/smart-wallets/AccountAbs
import { AccountAbstractionSummary } from "components/smart-wallets/AccountAbstractionAnalytics/AccountAbstractionSummary";
import { notFound, redirect } from "next/navigation";
import type { SearchParams } from "nuqs/server";
import { getAuthToken } from "../../../../../../api/lib/getAuthToken";
import { searchParamLoader } from "./search-params";

interface PageParams {
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@ import { ChakraProviderSetup } from "@/components/ChakraProviderSetup";
import { UnderlineLink } from "@/components/ui/UnderlineLink";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
import { getAuthToken } from "@app/api/lib/getAuthToken";
import { getValidTeamPlan } from "@app/team/components/TeamHeader/getValidTeamPlan";
import { AccountAbstractionSettingsPage } from "components/smart-wallets/SponsorshipPolicies";
import { CircleAlertIcon } from "lucide-react";
import { redirect } from "next/navigation";
import { getAuthToken } from "../../../../../../../api/lib/getAuthToken";
import { getValidTeamPlan } from "../../../../../../components/TeamHeader/getValidTeamPlan";

export default async function Page(props: {
params: Promise<{ team_slug: string; project_slug: string }>;
Original file line number Diff line number Diff line change
@@ -19,9 +19,10 @@ import { SmartAccountIcon } from "../../../../../(dashboard)/(chain)/components/

export function ProjectSidebarLayout(props: {
layoutPath: string;
engineLinkType: "cloud" | "dedicated";
children: React.ReactNode;
}) {
const { layoutPath, children } = props;
const { layoutPath, engineLinkType, children } = props;

return (
<FullWidthSidebarLayout
@@ -39,11 +40,11 @@ export function ProjectSidebarLayout(props: {
},
{
label: "Account Abstraction",
href: `${layoutPath}/connect/account-abstraction`,
href: `${layoutPath}/account-abstraction`,
icon: SmartAccountIcon,
},
{
href: `${layoutPath}/connect/universal-bridge`,
href: `${layoutPath}/universal-bridge`,
icon: PayIcon,
label: "Universal Bridge",
},
@@ -62,9 +63,18 @@ export function ProjectSidebarLayout(props: {
icon: CoinsIcon,
},
{
href: `${layoutPath}/engine`,
href:
engineLinkType === "cloud"
? `${layoutPath}/transactions`
: `${layoutPath}/engine/dedicated`,
label: "Transactions",
icon: ArrowLeftRightIcon,
isActive: (pathname) => {
return (
pathname.startsWith(`${layoutPath}/transactions`) ||
pathname.startsWith(`${layoutPath}/engine/dedicated`)
);
},
},
{
href: `${layoutPath}/insight`,
Loading