diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/PageHeader.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/PageHeader.tsx new file mode 100644 index 00000000000..593b8e1fe8a --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/PageHeader.tsx @@ -0,0 +1,24 @@ +import { TrackedLinkTW } from "@/components/ui/tracked-link"; + +export function PageHeader() { + return ( +
+

In-App Wallets

+
+

+ A wallet infrastructure that enables apps to create, manage, and control + their users wallets. Email login, social login, and bring-your-own auth + supported.{" "} + + Learn more + +

+
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/[clientId]/page.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/[clientId]/page.tsx new file mode 100644 index 00000000000..2b928b9944f --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/[clientId]/page.tsx @@ -0,0 +1,50 @@ +import { redirect } from "next/navigation"; +import { EmbeddedWallets } from "../../../../../../components/embedded-wallets"; +import { getAuthToken } from "../../../../../api/lib/getAuthToken"; +import { PageHeader } from "../PageHeader"; +import { getInAppWalletSupportedAPIKeys } from "../getInAppWalletSupportedAPIKeys"; +import { InAppWalletsAPIKeysMenu } from "../inAppWalletsAPIKeysMenu"; + +export default async function Page(props: { + params: { + clientId: string; + }; + searchParams: { + tab?: string; + }; +}) { + const authToken = getAuthToken(); + const { clientId } = props.params; + + if (!authToken) { + redirect( + `/login?next=${encodeURIComponent(`/dashboard/connect/in-app-wallets/${clientId}`)}`, + ); + } + + const apiKeys = await getInAppWalletSupportedAPIKeys(); + const apiKey = apiKeys.find((key) => key.key === clientId); + + if (!apiKey) { + redirect("/dashboard/connect/in-app-wallets"); + } + + return ( +
+ {/* header */} +
+ +
+ +
+
+ +
+ +
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/getInAppWalletSupportedAPIKeys.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/getInAppWalletSupportedAPIKeys.ts new file mode 100644 index 00000000000..5c8454b4235 --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/getInAppWalletSupportedAPIKeys.ts @@ -0,0 +1,7 @@ +import { getApiKeys } from "../../../../api/lib/getAPIKeys"; + +export async function getInAppWalletSupportedAPIKeys() { + return (await getApiKeys()).filter((key) => { + return !!(key.services || []).find((srv) => srv.name === "embeddedWallets"); + }); +} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/inAppWalletsAPIKeysMenu.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/inAppWalletsAPIKeysMenu.tsx new file mode 100644 index 00000000000..9d1ee930bcf --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/inAppWalletsAPIKeysMenu.tsx @@ -0,0 +1,21 @@ +"use client"; + +import { useDashboardRouter } from "@/lib/DashboardRouter"; +import type { ApiKey } from "@3rdweb-sdk/react/hooks/useApi"; +import { ApiKeysMenu } from "../../../../../components/settings/ApiKeys/Menu"; + +export function InAppWalletsAPIKeysMenu(props: { + apiKeys: Pick[]; + selectedAPIKey: Pick; +}) { + const router = useDashboardRouter(); + return ( + { + router.push(`/dashboard/connect/in-app-wallets/${key.key}`); + }} + /> + ); +} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/layout.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/layout.tsx new file mode 100644 index 00000000000..2c9758c30e2 --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/layout.tsx @@ -0,0 +1,17 @@ +import { AnalyticsCallout } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/AnalyticsCallout"; +import { InAppWaletFooterSection } from "../../../../team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/footer"; + +export default function Layout(props: { + children: React.ReactNode; +}) { + return ( +
+ {props.children} +
+ {/* Footer */} + +
+ +
+ ); +} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/page.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/page.tsx new file mode 100644 index 00000000000..c4d75d74e9c --- /dev/null +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/in-app-wallets/page.tsx @@ -0,0 +1,30 @@ +import { redirect } from "next/navigation"; +import { NoApiKeys } from "../../../../../components/settings/ApiKeys/NoApiKeys"; +import { getAuthToken } from "../../../../api/lib/getAuthToken"; +import { PageHeader } from "./PageHeader"; +import { getInAppWalletSupportedAPIKeys } from "./getInAppWalletSupportedAPIKeys"; + +export default async function Page() { + const authToken = getAuthToken(); + + if (!authToken) { + redirect( + `/login?next=${encodeURIComponent("/dashboard/connect/in-app-wallets")}`, + ); + } + + const apiKeys = await getInAppWalletSupportedAPIKeys(); + const firstKey = apiKeys[0]; + + if (firstKey) { + redirect(`/dashboard/connect/in-app-wallets/${firstKey.key}`); + } + + return ( +
+ +
+ +
+ ); +} diff --git a/apps/dashboard/src/components/embedded-wallets/index.tsx b/apps/dashboard/src/components/embedded-wallets/index.tsx index 8f292be8898..6c6ce2a84c3 100644 --- a/apps/dashboard/src/components/embedded-wallets/index.tsx +++ b/apps/dashboard/src/components/embedded-wallets/index.tsx @@ -2,7 +2,6 @@ import { TabButtons } from "@/components/ui/tabs"; import type { ApiKey } from "@3rdweb-sdk/react/hooks/useApi"; -import { useSearchParams } from "next/navigation"; import { useState } from "react"; import { InAppWalletSettingsPage } from "./Configure"; import { InAppWalletUsersPageContent } from "./Users"; @@ -19,16 +18,16 @@ interface EmbeddedWalletsProps { | "key" >; trackingCategory: string; + defaultTab: 0 | 1; } export const EmbeddedWallets: React.FC = ({ apiKey, trackingCategory, + defaultTab, }) => { - const searchParams = useSearchParams(); - const defaultTabIndex = searchParams?.get("tab") === "1" ? 1 : 0; const [selectedTab, setSelectedTab] = useState<"users" | "config">( - defaultTabIndex === 0 ? "users" : "config", + defaultTab === 0 ? "users" : "config", ); function updateSearchParams(value: string) { diff --git a/apps/dashboard/src/page-id.ts b/apps/dashboard/src/page-id.ts index 02ee6d12492..dd488d90025 100644 --- a/apps/dashboard/src/page-id.ts +++ b/apps/dashboard/src/page-id.ts @@ -98,8 +98,6 @@ export enum PageId { // thirdweb.com/dashboard/connect/smart-wallet DashboardConnectAccountAbstraction = "dashboard-wallets-smart-wallet", - // thirdweb.com/dashboard/connect/embedded - DashboardConnectEmbeddedWallets = "dashboard-wallets-embedded", // thirdweb.com/dashboard/contracts/build DashboardContractsBuild = "dashboard-contracts-build", diff --git a/apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx b/apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx deleted file mode 100644 index 8176ac64831..00000000000 --- a/apps/dashboard/src/pages/dashboard/connect/in-app-wallets.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { Spinner } from "@/components/ui/Spinner/Spinner"; -import { TrackedLinkTW } from "@/components/ui/tracked-link"; -import { type ApiKey, useApiKeys } from "@3rdweb-sdk/react/hooks/useApi"; -import { useLoggedInUser } from "@3rdweb-sdk/react/hooks/useLoggedInUser"; -import { AppLayout } from "components/app-layouts/app"; -import { EmbeddedWallets } from "components/embedded-wallets"; -import { ApiKeysMenu } from "components/settings/ApiKeys/Menu"; -import { NoApiKeys } from "components/settings/ApiKeys/NoApiKeys"; -// import { ConnectSidebar } from "core-ui/sidebar/connect"; -import { useRouter } from "next/router"; -import { PageId } from "page-id"; -import { useMemo, useState } from "react"; -import type { ThirdwebNextPage } from "utils/types"; -import { ConnectSidebarLayout } from "../../../app/(dashboard)/dashboard/connect/DashboardConnectLayout"; -import { AnalyticsCallout } from "../../../app/team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/AnalyticsCallout"; -import { InAppWaletFooterSection } from "../../../app/team/[team_slug]/[project_slug]/connect/in-app-wallets/_components/footer"; - -const TRACKING_CATEGORY = "embedded-wallet"; - -const DashboardConnectEmbeddedWallets: ThirdwebNextPage = () => { - const router = useRouter(); - const defaultClientId = router.query.clientId?.toString(); - const { isPending } = useLoggedInUser(); - const keysQuery = useApiKeys(); - - const [selectedKey_, setSelectedKey] = useState(); - - const apiKeys = useMemo(() => { - return (keysQuery?.data || []).filter((key) => { - return !!(key.services || []).find( - (srv) => srv.name === "embeddedWallets", - ); - }); - }, [keysQuery]); - - const hasApiKeys = apiKeys.length > 0; - - // compute the actual selected key based on if there is a state, if there is a query param, or otherwise the first one - const selectedKey = useMemo(() => { - if (selectedKey_) { - return selectedKey_; - } - if (apiKeys.length) { - if (defaultClientId) { - return apiKeys.find((k) => k.key === defaultClientId); - } - return apiKeys[0]; - } - return undefined; - }, [apiKeys, defaultClientId, selectedKey_]); - - if (isPending) { - return ( -
- -
- ); - } - - return ( -
-
-
-

- In-App Wallets -

- -
- -

- A wallet infrastructure that enables apps to create, manage, and - control their users wallets. Email login, social login, and - bring-your-own auth supported.{" "} - - Learn more - -

-
- -
- {hasApiKeys && selectedKey && ( - - )} -
-
- -
- - {keysQuery.isPending ? ( -
- -
- ) : ( - <> - {!hasApiKeys && } - - {hasApiKeys && selectedKey && ( - - )} - - )} - -
- -
- - -
- ); -}; - -DashboardConnectEmbeddedWallets.getLayout = (page, props) => ( - - {page} - -); - -DashboardConnectEmbeddedWallets.pageId = PageId.DashboardConnectEmbeddedWallets; - -export default DashboardConnectEmbeddedWallets;