diff --git a/apps/dashboard/framer-rewrites.js b/apps/dashboard/framer-rewrites.js index a51116e63b7..c957cd5177e 100644 --- a/apps/dashboard/framer-rewrites.js +++ b/apps/dashboard/framer-rewrites.js @@ -21,6 +21,7 @@ module.exports = [ "/rpc", "/insight", "/storage", + "/gateway", // -- end scale category // -- ai diff --git a/apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx b/apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx index 892d6ba1671..26ce5518be2 100644 --- a/apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx +++ b/apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx @@ -67,7 +67,7 @@ export function FullWidthSidebarLayout(props: { )} > {/* left - sidebar */} - + diff --git a/apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx b/apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx index 6a027f917f4..f7877cfbca3 100644 --- a/apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx +++ b/apps/dashboard/src/@/components/blocks/project-page/project-page-header.tsx @@ -66,13 +66,16 @@ export type ProjectPageHeaderProps = { href: string; }; + className?: string; // TODO: add task card component task?: never; }; export function ProjectPageHeader(props: ProjectPageHeaderProps) { return ( -
+
{/* top row */}
{/* left - icon */} diff --git a/apps/dashboard/src/@/components/blocks/project-page/project-page.tsx b/apps/dashboard/src/@/components/blocks/project-page/project-page.tsx index f72bf644ed0..fa2f04083f0 100644 --- a/apps/dashboard/src/@/components/blocks/project-page/project-page.tsx +++ b/apps/dashboard/src/@/components/blocks/project-page/project-page.tsx @@ -13,13 +13,19 @@ type ProjectPageProps = { header: ProjectPageHeaderProps; footer?: ProjectPageFooterProps; tabs?: TabPathLink[]; + containerClassName?: string; }; export function ProjectPage(props: React.PropsWithChildren) { return (
- + 0 ? "pt-8 pb-6" : "py-8", + )} + /> {props.tabs && ( ) { )}
-
{props.children}
+
+ {props.children} +
{props.footer && (
diff --git a/apps/dashboard/src/@/icons/ConnectSDKIcon.tsx b/apps/dashboard/src/@/icons/ConnectSDKIcon.tsx deleted file mode 100644 index fa1e9a2e7f8..00000000000 --- a/apps/dashboard/src/@/icons/ConnectSDKIcon.tsx +++ /dev/null @@ -1,21 +0,0 @@ -export function ConnectSDKIcon(props: { className?: string }) { - return ( - - - - ); -} diff --git a/apps/dashboard/src/@/icons/NebulaIcon.tsx b/apps/dashboard/src/@/icons/NebulaIcon.tsx deleted file mode 100644 index 1a59d089f01..00000000000 --- a/apps/dashboard/src/@/icons/NebulaIcon.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export function NebulaIcon(props: { className?: string }) { - return ( - - - - - ); -} diff --git a/apps/dashboard/src/@/icons/brand-icons/ExpoIcon.tsx b/apps/dashboard/src/@/icons/brand-icons/ExpoIcon.tsx new file mode 100644 index 00000000000..3b45bc2cab5 --- /dev/null +++ b/apps/dashboard/src/@/icons/brand-icons/ExpoIcon.tsx @@ -0,0 +1,21 @@ +export function ExpoIcon(props: { className?: string }) { + return ( + + ); +} diff --git a/apps/dashboard/src/@/icons/brand-icons/NextjsIcon.tsx b/apps/dashboard/src/@/icons/brand-icons/NextjsIcon.tsx new file mode 100644 index 00000000000..0fd37729730 --- /dev/null +++ b/apps/dashboard/src/@/icons/brand-icons/NextjsIcon.tsx @@ -0,0 +1,59 @@ +export function NextjsIcon(props: { className?: string }) { + return ( + + ); +} diff --git a/apps/dashboard/src/@/icons/brand-icons/NodeJSIcon.tsx b/apps/dashboard/src/@/icons/brand-icons/NodeJSIcon.tsx new file mode 100644 index 00000000000..0f430bee249 --- /dev/null +++ b/apps/dashboard/src/@/icons/brand-icons/NodeJSIcon.tsx @@ -0,0 +1,20 @@ +export function NodeJSIcon(props: { className?: string }) { + return ( + + ); +} diff --git a/apps/dashboard/src/@/icons/brand-icons/ViteIcon.tsx b/apps/dashboard/src/@/icons/brand-icons/ViteIcon.tsx new file mode 100644 index 00000000000..d08367f5d9f --- /dev/null +++ b/apps/dashboard/src/@/icons/brand-icons/ViteIcon.tsx @@ -0,0 +1,23 @@ +export function ViteIcon(props: { className?: string }) { + return ( + + ); +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/SupportedProductsSection.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/SupportedProductsSection.tsx index ec7ec06c3af..957e8c64255 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/SupportedProductsSection.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/SupportedProductsSection.tsx @@ -1,55 +1,112 @@ +import { BotIcon, CodeIcon, CoinsIcon } from "lucide-react"; import Link from "next/link"; -import type { ChainMetadataWithServices } from "@/types/chain"; -import { products } from "../../../../components/server/products"; +import { useMemo } from "react"; +import { BridgeIcon } from "@/icons/BridgeIcon"; +import { PayIcon } from "@/icons/PayIcon"; +import { WalletProductIcon } from "@/icons/WalletProductIcon"; +import type { + ChainMetadataWithServices, + ChainSupportedService, +} from "@/types/chain"; import { SectionTitle } from "./SectionTitle"; export function SupportedProductsSection(props: { services: ChainMetadataWithServices["services"]; }) { - const enabledProducts = products.filter((product) => { - return props.services.find( - (service) => service.service === product.id && service.enabled, + const enabledServices = useMemo(() => { + return props.services.reduce( + (acc, service) => { + acc[service.service] = service.enabled; + return acc; + }, + {} as Record, ); - }); - - if (enabledProducts.length === 0) { - return null; - } + }, [props.services]); return (
- {enabledProducts.map((product) => { - return ( -
-
-
- -
-
-
-

- - {product.name} - -

-

- {product.description} -

-
-
- ); - })} + {enabledServices["connect-sdk"] && ( + + )} + + {enabledServices["account-abstraction"] && ( + + )} + + {enabledServices.pay && ( + + )} + + {enabledServices.contracts && ( + + )} + + + +
); } + +function ProductCard(props: { + icon: React.FC<{ className?: string }>; + link: string; + name: string; + description: string; +}) { + return ( +
+
+
+ +
+
+
+

+ + {props.name} + +

+

{props.description}

+
+
+ ); +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/client/filters.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/client/filters.tsx index cb69e35cdd2..5a3f34c480a 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/client/filters.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/client/filters.tsx @@ -15,7 +15,7 @@ import { import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Separator } from "@/components/ui/separator"; import { useDashboardRouter } from "@/lib/DashboardRouter"; -import { products } from "../../../components/server/products"; +import { services } from "../../../components/server/products"; function cleanUrl(url: string) { if (url.endsWith("?")) { @@ -345,7 +345,7 @@ export const ChainServiceFilter: React.FC = ({ const section = ( - {products.map((product) => ( + {services.map((product) => (
= ({ } const firstFilter = allFilters[0]; - const name = products.find((p) => p.id === firstFilter)?.name; + const name = services.find((p) => p.id === firstFilter)?.name; const plus = allFilters.length > 1 ? ` +${allFilters.length - 1}` : ""; return [`${name}${plus}`, true]; diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/server/chainlist-row.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/server/chainlist-row.tsx index fefb8e26749..01dc2d26000 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/server/chainlist-row.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/chainlist/components/server/chainlist-row.tsx @@ -12,7 +12,7 @@ import { ToolTipLabel } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import type { ChainSupportedService } from "@/types/chain"; import { ChainIcon } from "../../../components/server/chain-icon"; -import { products } from "../../../components/server/products"; +import { services } from "../../../components/server/products"; import { getCustomChainMetadata } from "../../../utils"; type ChainListRowProps = { @@ -83,7 +83,7 @@ export function ChainListRow({
- {products.map((p) => { + {services.map((p) => { return ( ; - description: string; link: string; }>; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportTicketForm.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportTicketForm.tsx index b623117fcad..967b2826698 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportTicketForm.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/SupportTicketForm.tsx @@ -26,14 +26,6 @@ const EngineSupportForm = dynamic( ssr: false, }, ); -const ContractSupportForm = dynamic( - () => - import("./contact-forms/contracts").then((mod) => mod.ContractSupportForm), - { - loading: () => , - ssr: false, - }, -); const AccountSupportForm = dynamic( () => import("./contact-forms/account").then((mod) => mod.AccountSupportForm), { @@ -48,14 +40,6 @@ const OtherSupportForm = dynamic( ssr: false, }, ); -const PaymentsSupportForm = dynamic( - () => - import("./contact-forms/payments").then((mod) => mod.PaymentsSupportForm), - { - loading: () => , - ssr: false, - }, -); const TokensMarketplaceSupportForm = dynamic( () => import("./contact-forms/tokens-marketplace").then( @@ -68,13 +52,14 @@ const TokensMarketplaceSupportForm = dynamic( ); const productOptions = [ - { component: , label: "Wallets" }, - { component: , label: "Transactions" }, - { component: , label: "Payments" }, - { component: , label: "Contracts" }, + { component: , label: "Working with User Wallets" }, + { + component: , + label: "Using API/SDK’s, errored transactions", + }, { component: , - label: "Tokens / Marketplace", + label: "Creating, Bridging and swapping tokens", }, { component: , label: "Account" }, { component: , label: "Other" }, diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/AffectedAreaInput.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/AffectedAreaInput.tsx deleted file mode 100644 index 9f0d8170098..00000000000 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/AffectedAreaInput.tsx +++ /dev/null @@ -1,67 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { DescriptionInput } from "../../shared/SupportForm_DescriptionInput"; -import { SupportForm_SelectInput } from "../../shared/SupportForm_SelectInput"; -import { SupportForm_TextInput } from "../../shared/SupportForm_TextInput"; -import { UnitySupportForm } from "../../shared/SupportForm_UnityInput"; - -const AFFECTED_AREAS = ["Dashboard", "Application"]; - -export const AffectedAreaInput = () => { - const [selectedAffectedArea, setSelectedAffectedArea] = useState(""); - const [selectedSDK, setSelectedSDK] = useState(""); - const [description, setDescription] = useState(""); - const [sdkDescription, setSdkDescription] = useState(""); - - return ( - <> - - {selectedAffectedArea && - (selectedAffectedArea === "Application" ? ( - <> - - {selectedSDK && ( - <> - {selectedSDK === "Unity" && } - - - - - )} - - ) : ( - - ))} - - ); -}; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/index.tsx index 5bcd72eea3c..e2c69ba865c 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/index.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/connect/index.tsx @@ -1,116 +1,91 @@ +"use client"; + import { type ReactElement, useState } from "react"; import { DescriptionInput } from "../../shared/SupportForm_DescriptionInput"; import { SupportForm_SelectInput } from "../../shared/SupportForm_SelectInput"; import { SupportForm_TextInput } from "../../shared/SupportForm_TextInput"; -import { UnitySupportForm } from "../../shared/SupportForm_UnityInput"; -import { AffectedAreaInput } from "./AffectedAreaInput"; type ProblemAreaItem = { label: string; component: ReactElement; }; -const SDKVersionInput = () => ( - -); +const SocialEmailLoginIssuesComponent = () => { + const [description, setDescription] = useState(""); + return ( + <> + + + + ); +}; -const OSSelect = () => { - const [selectedOS, setSelectedOS] = useState(""); +const UserWalletCustomAuthComponent = () => { + const [description, setDescription] = useState(""); return ( - + <> + + + + ); }; -const DescriptionInputWrapper = () => { +const AccountAbstractionComponent = () => { + const [description, setDescription] = useState(""); + return ( + <> + + + + ); +}; + +const ThirdPartyEOAWalletsComponent = () => { const [description, setDescription] = useState(""); return ; }; const PROBLEM_AREAS: ProblemAreaItem[] = [ { - component: , - label: "In-app wallet login issues", - }, - { - component: , - label: "In-app wallet transaction issues", + component: , + label: "Social/Email login issues", }, { - component: , - label: "In-app wallet Custom Auth", + component: , + label: "User wallet with custom auth", }, { - component: , + component: , label: "Account Abstraction", }, { - component: ( - <> - - - - - ), - label: "thirdweb SDKs", - }, - { - component: ( - <> - - - - - ), - label: "Unity SDK", - }, - { - component: ( - <> - - - - - - - ), - label: ".NET SDK", - }, - { - component: , - label: "Pay", - }, - { - component: , - label: "Auth", + component: , + label: "Third party/EOA wallets", }, ]; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/contracts/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/contracts/index.tsx deleted file mode 100644 index d9413073ed0..00000000000 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/contracts/index.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { type ReactElement, useState } from "react"; -import { DescriptionInput } from "../../shared/SupportForm_DescriptionInput"; -import { SupportForm_SelectInput } from "../../shared/SupportForm_SelectInput"; -import { SupportForm_TextInput } from "../../shared/SupportForm_TextInput"; - -type ProblemAreaItem = { - label: string; - component: ReactElement; -}; - -const NetworkInput = () => ( - -); - -const ContractAddressInput = () => ( - -); - -const ContractFunctionInput = () => ( - -); - -const ContractTypeInput = () => ( - -); - -const ContractAffectedAreaInput = () => { - const [selectedAffectedArea, setSelectedAffectedArea] = useState(""); - return ( - - ); -}; - -const DescriptionInputWrapper = () => { - const [description, setDescription] = useState(""); - return ; -}; - -const CONTRACT_PROBLEM_AREAS: ProblemAreaItem[] = [ - { - component: ( - <> - - - - - - ), - label: "Deploying a contract", - }, - { - component: ( - <> - - - - - - ), - label: "Contract verification", - }, - { - component: ( - <> - - - - - - - ), - label: "Calling a function in my contract", - }, - { - component: ( - <> - - - ), - label: "Developing a custom contract", - }, - { - component: ( - <> - - - ), - label: "Other", - }, -]; - -export function ContractSupportForm() { - const [problemArea, setProblemArea] = useState(""); - return ( - <> - o.label)} - promptText="Select a problem area" - required={true} - value={problemArea} - /> - {CONTRACT_PROBLEM_AREAS.find((o) => o.label === problemArea)?.component} - - ); -} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/engine/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/engine/index.tsx index 4ba340c4614..beb718e0ef0 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/engine/index.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/engine/index.tsx @@ -2,56 +2,62 @@ import { useState } from "react"; import { DescriptionInput } from "../../shared/SupportForm_DescriptionInput"; import { SupportForm_SelectInput } from "../../shared/SupportForm_SelectInput"; import { SupportForm_TextInput } from "../../shared/SupportForm_TextInput"; +import { UnitySupportForm } from "../../shared/SupportForm_UnityInput"; -const ENGINE_TYPES = ["Cloud (V3)", "Dedicated (V2)"]; -const ENGINE_PROBLEM_AREAS = [ - "SSL Issues", - "Transaction queueing issues", - "401 - Unauthorized", - "404 - Endpoint Not Found", - "Other", +const API_SDK_OPTIONS = [ + "API endpoint", + "React/TypeScript", + "Unity/.NET", + "React Native", ]; export function EngineSupportForm() { - const [selectedEngineType, setSelectedEngineType] = useState(""); - const [problemArea, setProblemArea] = useState(""); + const [selectedSDK, setSelectedSDK] = useState(""); const [description, setDescription] = useState(""); return ( <> {" "} - {selectedEngineType && ( + value={selectedSDK} + /> + {selectedSDK && ( <> - - - {problemArea && ( - <> + {selectedSDK === "Unity/.NET" ? ( + + ) : ( + selectedSDK !== "API endpoint" && ( - - + ) + )} + + {selectedSDK === "API endpoint" && ( + )} + )} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/other/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/other/index.tsx index 075b94f55a1..e0a4b474ea7 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/other/index.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/other/index.tsx @@ -14,6 +14,7 @@ const OTHER_PROBLEM_AREAS = [ "Bug report", "Documentation", "Integration help", + "Agents/x402 and AI", "Other", ]; export function OtherSupportForm() { diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/payments/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/payments/index.tsx deleted file mode 100644 index 052245261b1..00000000000 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/payments/index.tsx +++ /dev/null @@ -1,55 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { DescriptionInput } from "../../shared/SupportForm_DescriptionInput"; -import { SupportForm_SelectInput } from "../../shared/SupportForm_SelectInput"; -import { SupportForm_TextInput } from "../../shared/SupportForm_TextInput"; - -const PAYMENT_AREAS = ["Dashboard", "Application"]; - -export function PaymentsSupportForm() { - const [area, setArea] = useState(""); - const [description, setDescription] = useState(""); - - return ( - <> - - {area === "Application" && ( - <> - - - - - )} - {(area === "Application" || area === "Dashboard") && ( - - )} - - ); -} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/tokens-marketplace/index.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/tokens-marketplace/index.tsx index 89d80267649..911b886bdfd 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/tokens-marketplace/index.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/support/_components/contact-forms/tokens-marketplace/index.tsx @@ -8,10 +8,10 @@ export function TokensMarketplaceSupportForm() { return ( <> + ); diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/chart/AiTokenUsageChartCard.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/chart/AiTokenUsageChartCard.tsx index b38e0505a6c..c5ca8895970 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/chart/AiTokenUsageChartCard.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/chart/AiTokenUsageChartCard.tsx @@ -1,11 +1,11 @@ "use client"; import { format } from "date-fns"; +import { BotIcon } from "lucide-react"; import { useMemo } from "react"; import { ThirdwebBarChart } from "@/components/blocks/charts/bar-chart"; import { DocLink } from "@/components/blocks/DocLink"; import { ExportToCSVButton } from "@/components/blocks/ExportToCSVButton"; import type { ChartConfig } from "@/components/ui/chart"; -import { NebulaIcon } from "@/icons/NebulaIcon"; import type { AIUsageStats } from "@/types/analytics"; type ChartData = Record & { @@ -106,7 +106,7 @@ function AiTokenUsageEmptyChartState() {
diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/page.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/page.tsx index 2f818455eec..661426788dd 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/page.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/analytics/page.tsx @@ -1,3 +1,4 @@ +import { BotIcon } from "lucide-react"; import { redirect } from "next/navigation"; import { ResponsiveSearchParamsProvider } from "responsive-rsc"; import { getAuthToken } from "@/api/auth-token"; @@ -6,7 +7,6 @@ import type { DurationId } from "@/components/analytics/date-range-selector"; import { ResponsiveTimeFilters } from "@/components/analytics/responsive-time-filters"; import { ProjectPage } from "@/components/blocks/project-page/project-page"; import { getClientThirdwebClient } from "@/constants/thirdweb-client.client"; -import { NebulaIcon } from "@/icons/NebulaIcon"; import { getFiltersFromSearchParams } from "@/lib/time"; import { loginRedirect } from "@/utils/redirects"; import { AiAnalytics } from "./chart"; @@ -58,7 +58,7 @@ export default async function Page(props: {
- + thirdweb AI
diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/Chats.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/Chats.tsx index f5c41ed3440..7dc23ca4b67 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/Chats.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/Chats.tsx @@ -1,10 +1,9 @@ import { MarkdownRenderer } from "@workspace/ui/components/markdown-renderer"; import { ScrollShadow } from "@workspace/ui/components/scroll-shadow"; -import { AlertCircleIcon } from "lucide-react"; +import { AlertCircleIcon, BotIcon } from "lucide-react"; import { useEffect, useRef } from "react"; import type { ThirdwebClient } from "thirdweb"; import type { Project } from "@/api/project/projects"; -import { NebulaIcon } from "@/icons/NebulaIcon"; import { cn } from "@/lib/utils"; import type { NebulaSwapData, @@ -238,11 +237,11 @@ function RenderMessage(props: { )} > {message.type === "presence" && ( - + )} {message.type === "assistant" && ( - + )} {message.type === "error" && ( diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/EmptyStateChatPageContent.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/EmptyStateChatPageContent.tsx index b2614f74ee9..ad0c25a9578 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/EmptyStateChatPageContent.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/ai/components/EmptyStateChatPageContent.tsx @@ -1,9 +1,8 @@ "use client"; -import { ArrowUpRightIcon, InfoIcon } from "lucide-react"; +import { ArrowUpRightIcon, BotIcon, InfoIcon } from "lucide-react"; import type { ThirdwebClient } from "thirdweb"; import { Button } from "@/components/ui/button"; -import { NebulaIcon } from "@/icons/NebulaIcon"; import { cn } from "@/lib/utils"; import type { NebulaContext, NebulaUserMessage } from "../api/types"; import { examplePrompts } from "../data/examplePrompts"; @@ -33,7 +32,7 @@ export function EmptyStateChatPageContent(props: {
- +
diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ClientIDSection.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ClientIDSection.tsx index 0dd8e8119f4..d9f9d0bc1f3 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ClientIDSection.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ClientIDSection.tsx @@ -3,8 +3,8 @@ import { CopyTextButton } from "@/components/ui/CopyTextButton"; export function ClientIDSection(props: { clientId: string }) { return (
-

Client ID

-

+

Client ID

+

Identifies your application

diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/CodeSelector.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/CodeSelector.tsx new file mode 100644 index 00000000000..4c6d4fd6e8d --- /dev/null +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/CodeSelector.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { useState } from "react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +export function CodeShowcase(props: { + title: string; + tabs: Array<{ + label: string; + code: React.ReactNode; + }>; +}) { + const [selectedTab, setSelectedTab] = useState(props.tabs[0]?.label || ""); + + return ( +
+
+

{props.title}

+ +
+ + {props.tabs.find((tab) => tab.label === selectedTab)?.code} +
+ ); +} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx index e48d6d82575..190484c7c55 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx @@ -24,6 +24,7 @@ type Story = StoryObj; export const Default: Story = { args: { + projectWalletSection: undefined, project: { ...projectStub("foo", "bar"), secretKeys: [ diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx index b1f51f3857f..5ddec808e09 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx @@ -1,26 +1,40 @@ +import { Button } from "@workspace/ui/components/button"; +import { CodeServer } from "@workspace/ui/components/code/code.server"; import { - ArrowLeftRightIcon, + ArrowUpRightIcon, + BotIcon, ChevronRightIcon, - ExternalLinkIcon, + CoinsIcon, + DoorOpenIcon, } from "lucide-react"; import Link from "next/link"; import type { Project } from "@/api/project/projects"; -import { CodeServer } from "@/components/ui/code/code.server"; +import { BridgeIcon } from "@/icons/BridgeIcon"; import { DotNetIcon } from "@/icons/brand-icons/DotNetIcon"; -import { GithubIcon } from "@/icons/brand-icons/GithubIcon"; +import { ExpoIcon } from "@/icons/brand-icons/ExpoIcon"; +import { NextjsIcon } from "@/icons/brand-icons/NextjsIcon"; +import { NodeJSIcon } from "@/icons/brand-icons/NodeJSIcon"; import { ReactIcon } from "@/icons/brand-icons/ReactIcon"; import { TypeScriptIcon } from "@/icons/brand-icons/TypeScriptIcon"; import { UnityIcon } from "@/icons/brand-icons/UnityIcon"; import { UnrealIcon } from "@/icons/brand-icons/UnrealIcon"; -import { ContractIcon } from "@/icons/ContractIcon"; +import { ViteIcon } from "@/icons/brand-icons/ViteIcon"; import { PayIcon } from "@/icons/PayIcon"; +import { WalletProductIcon } from "@/icons/WalletProductIcon"; import { ClientIDSection } from "./ClientIDSection"; +import { CodeShowcase } from "./CodeSelector"; import { SecretKeySection } from "./SecretKeySection"; -export function ProjectFTUX(props: { project: Project; teamSlug: string }) { +export function ProjectFTUX(props: { + project: Project; + teamSlug: string; + projectWalletSection: React.ReactNode; +}) { return ( -
+
+ {props.projectWalletSection} + -

- Integrate API key -

+
+
+

API Keys

+

+ Your API key is used to authenticate and integrate your application. +

+ +
-
+
{secretKeyMasked && ( @@ -53,23 +84,74 @@ function IntegrateAPIKeySection({ project }: { project: Project }) { /> )}
+
+
+ ); +} -
-
-

- Run this command in your terminal to send a test transaction using - your Project Wallet. -

- -
+function GetStartedSection({ project }: { project: Project }) { + return ( +
+
+

+ Get Started +

+

+ Send a test transaction using your project wallet +

+ +
+ + + ), + }, + { + label: "JavaScript", + code: ( + + ), + }, + { + label: "Python", + code: ( + + ), + }, + ]} + />
); } + const curlCodeExample = (project: Project): string => `\ curl https://api.thirdweb.com/v1/transactions \\ --request POST \\ @@ -87,6 +169,40 @@ curl https://api.thirdweb.com/v1/transactions \\ }' `; +const fetchJSCodeExample = (project: Project): string => `\ +fetch("https://github.com/service/https://api.thirdweb.com/v1/transactions", { + method: "POST", + headers: { + "Content-Type": "application/json", + "x-secret-key": "${project.secretKeys[0]?.masked ?? ""}", + }, + body: JSON.stringify({ + chainId: 421614, + transactions: [ + { data: "0x", to: "vitalik.eth", value: "0" }, + ], + }), +}); +`; + +const pythonCodeExample = (project: Project): string => `\ +import requests + +url = "https://api.thirdweb.com/v1/transactions" +headers = { + "Content-Type": "application/json", + "x-secret-key": "${project.secretKeys[0]?.masked ?? ""}", +} +payload = { + "chainId": 421614, + "transactions": [ + { "data": "0x", "to": "vitalik.eth", "value": "0" }, + ], +} +response = requests.post(url, headers=headers, json=payload) +result = response.json() +`; + // products section ------------------------------------------------------------ function ProductsSection(props: { teamSlug: string; projectSlug: string }) { @@ -97,49 +213,60 @@ function ProductsSection(props: { teamSlug: string; projectSlug: string }) { icon: React.FC<{ className?: string }>; }> = [ { - description: - "Scale your application with a backend server to read, write, and deploy contracts at production-grade.", - href: `/team/${props.teamSlug}/${props.projectSlug}/transactions`, - icon: ArrowLeftRightIcon, - title: "Transactions", + icon: WalletProductIcon, + title: "Wallets", + description: "Wallets to read, write and transact", + href: `/team/${props.teamSlug}/${props.projectSlug}/wallets/user-wallets`, }, { - description: - "Deploy your own contracts or leverage existing solutions for onchain implementation", - href: `/team/${props.teamSlug}/${props.projectSlug}/contracts`, - icon: ContractIcon, - title: "Contracts", + icon: BridgeIcon, + title: "Bridge", + description: "Swap and bridge tokens", + href: `/team/${props.teamSlug}/${props.projectSlug}/bridge`, }, { - description: - "Bridge, swap, and purchase cryptocurrencies with any fiat options or tokens via cross-chain routing", - href: `/team/${props.teamSlug}/${props.projectSlug}/payments`, icon: PayIcon, - title: "Payments", + title: "x402", + description: "Native internet payments", + href: `/team/${props.teamSlug}/${props.projectSlug}/x402`, + }, + { + icon: DoorOpenIcon, + title: "Gateway", + description: "Blockchain connectivity and data access", + href: `/team/${props.teamSlug}/${props.projectSlug}/gateway/rpc`, + }, + { + icon: CoinsIcon, + title: "Tokens", + description: "Launch tokens and markets", + href: `/team/${props.teamSlug}/${props.projectSlug}/tokens`, + }, + { + icon: BotIcon, + title: "AI", + description: "Read and write onchain via AI agents", + href: `/team/${props.teamSlug}/${props.projectSlug}/ai`, }, ]; return (
-

- Complete your full-stack application -

-

- Tools to build frontend, backend, and onchain with built-in - infrastructure and analytics. +

Products

+

+ Everything you need to build full-stack applications, games, and agents.

- {/* Feature Cards */} -
+
{products.map((product) => ( - ))}
@@ -147,72 +274,51 @@ function ProductsSection(props: { teamSlug: string; projectSlug: string }) { ); } -function ProductCard(props: { - title: string; - description: string; - href: string; - icon: React.FC<{ className?: string }>; -}) { - return ( -
-
- -
-

- - {props.title} - -

-

{props.description}

-
- ); -} - // sdk section ------------------------------------------------------------ -type SDKCardProps = { +type IconCardProps = { name: string; + description: string | undefined; href: string; icon: React.FC<{ className?: string }>; - trackingLabel: string; }; -const sdks: SDKCardProps[] = [ +const sdks: IconCardProps[] = [ { href: "https://portal.thirdweb.com/sdk/typescript", icon: TypeScriptIcon, name: "TypeScript", - trackingLabel: "typescript", + description: undefined, }, { href: "https://portal.thirdweb.com/react/v5", icon: ReactIcon, name: "React", - trackingLabel: "react", + description: undefined, }, { href: "https://portal.thirdweb.com/react-native/v5", icon: ReactIcon, name: "React Native", - trackingLabel: "react_native", + description: undefined, }, { href: "https://portal.thirdweb.com/unity/v5", icon: UnityIcon, name: "Unity", - trackingLabel: "unity", + description: undefined, }, { href: "https://portal.thirdweb.com/unreal-engine", icon: UnrealIcon, name: "Unreal Engine", - trackingLabel: "unreal", + description: undefined, }, { href: "https://portal.thirdweb.com/dotnet", icon: DotNetIcon, name: ".NET", - trackingLabel: "dotnet", + description: undefined, }, ]; @@ -220,14 +326,14 @@ function SDKSection() { return (

Client SDKs

-
+
{sdks.map((sdk) => ( - ))}
@@ -235,10 +341,10 @@ function SDKSection() { ); } -function SDKCard(props: SDKCardProps) { +function IconCard(props: IconCardProps) { return ( -
-
+
+
@@ -246,16 +352,14 @@ function SDKCard(props: SDKCardProps) { {props.name}

-

- View Docs - -

+ {props.description && ( +

{props.description}

+ )}
); @@ -263,42 +367,47 @@ function SDKCard(props: SDKCardProps) { // starter kits section ------------------------------------------------------------ -type StartedKitCardProps = { - name: string; - href: string; - trackingLabel: string; -}; - -const startedKits: StartedKitCardProps[] = [ +const startedKits: IconCardProps[] = [ { href: "https://github.com/thirdweb-example/next-starter", name: "Next Starter", - trackingLabel: "next_starter", + icon: NextjsIcon, + description: undefined, }, { href: "https://github.com/thirdweb-example/vite-starter", name: "Vite Starter", - trackingLabel: "vite_starter", + icon: ViteIcon, + description: undefined, }, { href: "https://github.com/thirdweb-example/expo-starter", name: "Expo Starter", - trackingLabel: "expo_starter", + icon: ExpoIcon, + description: undefined, }, { href: "https://github.com/thirdweb-example/node-starter", name: "Node Starter", - trackingLabel: "node_starter", + icon: NodeJSIcon, + description: undefined, }, ]; function StarterKitsSection() { return (
-
-

Starter Kits

+
+
+

+ Starters +

+

+ Kickstart your development process with ready-to-ship repositories. +

+
-
+
{startedKits.map((kit) => ( - ))}
); } - -function StarterKitCard(props: StartedKitCardProps) { - return ( -
-
- -
- -
- - {props.name} - -

- View Repo - -

-
-
- ); -} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx index 3a6f24c9294..f7b6e4df883 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/SecretKeySection.tsx @@ -13,15 +13,15 @@ export function SecretKeySection(props: { return (
-

Secret Key

-

+

Secret Key

+

Identifies and authenticates your application from a backend.
{" "} This is not the full secret key, Refer to your saved secret key at the time of creation for the full secret key.

-
-
+
+
{secretKeyMasked}
diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx index 009229c4ac2..bd40487cb3e 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectSidebarLayout.tsx @@ -1,11 +1,10 @@ "use client"; import { Badge } from "@workspace/ui/components/badge"; import { - BookTextIcon, - BoxIcon, + BotIcon, DatabaseIcon, + DoorOpenIcon, HomeIcon, - RssIcon, Settings2Icon, WebhookIcon, } from "lucide-react"; @@ -15,7 +14,6 @@ import { } from "@/components/blocks/full-width-sidebar-layout"; import { BridgeIcon } from "@/icons/BridgeIcon"; import { ContractIcon } from "@/icons/ContractIcon"; -import { NebulaIcon } from "@/icons/NebulaIcon"; import { PayIcon } from "@/icons/PayIcon"; import { TokenIcon } from "@/icons/TokenIcon"; import { WalletProductIcon } from "@/icons/WalletProductIcon"; @@ -81,12 +79,12 @@ export function ProjectSidebarLayout(props: { }, { href: `${props.layoutPath}/ai`, - icon: NebulaIcon, + icon: BotIcon, label: "AI", }, { subMenu: { - icon: RssIcon, + icon: DoorOpenIcon, label: "Gateway", }, links: [ @@ -129,19 +127,6 @@ export function ProjectSidebarLayout(props: { icon: Settings2Icon, label: "Project Settings", }, - { - separator: true, - }, - { - href: "https://portal.thirdweb.com/", - icon: BookTextIcon, - label: "Documentation", - }, - { - href: "https://playground.thirdweb.com/wallets/sign-in/button", - icon: BoxIcon, - label: "Playground", - }, ] satisfies ShadcnSidebarLink[]; return ( diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx index 819d0c652f4..38f5d8da1c1 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx @@ -177,7 +177,7 @@ export function ProjectWalletDetailsSection(props: ProjectWalletControlsProps) { -
+

Wallet Address

-
+

Balance

diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx index 750c51f3328..4d64cb51ca8 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx @@ -49,6 +49,7 @@ const projectWallet2: ProjectWalletSummary = { export const NoProjectWalletSetNoManagedAccessToken: Story = { args: { + layout: "column", project: projectWithoutManagedAccessToken, client: storybookThirdwebClient, teamSlug: "bar", @@ -62,6 +63,7 @@ export const NoProjectWalletSetNoManagedAccessToken: Story = { export const NoProjectWalletSetWithManagedAccessToken: Story = { args: { + layout: "column", project: projectWithManagedAccessToken, client: storybookThirdwebClient, teamSlug: "bar", @@ -75,6 +77,7 @@ export const NoProjectWalletSetWithManagedAccessToken: Story = { export const NoProjectWalletSetWithManagedAccessTokenAndServerWallets: Story = { args: { + layout: "column", project: projectWithManagedAccessToken, teamSlug: "bar", client: storybookThirdwebClient, @@ -88,6 +91,7 @@ export const NoProjectWalletSetWithManagedAccessTokenAndServerWallets: Story = { export const NoProjectWalletSetLoading: Story = { args: { + layout: "column", project: projectWithManagedAccessToken, teamSlug: "bar", client: storybookThirdwebClient, @@ -101,6 +105,7 @@ export const NoProjectWalletSetLoading: Story = { export const ProjectWalletSetMultipleServerWallets: Story = { args: { + layout: "column", project: projectWithManagedAccessToken, teamSlug: "bar", client: storybookThirdwebClient, @@ -114,6 +119,7 @@ export const ProjectWalletSetMultipleServerWallets: Story = { export const ProjectWalletSetSingleServerWallet: Story = { args: { + layout: "column", project: projectWithManagedAccessToken, teamSlug: "bar", projectWallet: projectWallet1, diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx index e2a44ce2208..8175644e889 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx @@ -2,7 +2,8 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { UnderlineLink } from "@workspace/ui/components/UnderlineLink"; -import { ChevronDownIcon, XIcon } from "lucide-react"; +import { ArrowUpRightIcon, ChevronDownIcon, XIcon } from "lucide-react"; +import Link from "next/link"; import { useMemo, useState } from "react"; import { toast } from "sonner"; import type { ThirdwebClient } from "thirdweb"; @@ -29,6 +30,7 @@ import { Skeleton } from "@/components/ui/skeleton"; import { getClientThirdwebClient } from "@/constants/thirdweb-client.client"; import { useDashboardRouter } from "@/lib/DashboardRouter"; import type { ProjectWalletSummary } from "@/lib/server/project-wallet"; +import { cn } from "@/lib/utils"; import { updateDefaultProjectWallet } from "../../transactions/lib/vault.client"; import { CreateServerWallet } from "../../transactions/server-wallets/components/create-server-wallet.client"; import { ProjectWalletDetailsSection } from "./project-wallet-details"; @@ -131,11 +133,11 @@ function CreateProjectWalletSection(props: { Boolean(managementAccessToken) && serverWallets.length > 0; return ( -
+
- +
-

+

No Project Wallet set

@@ -276,10 +278,17 @@ export function ProjectWalletSectionUI(props: { projectWallet: ProjectWalletSummary | undefined; getProjectServerWallets: GetProjectServerWallets; client: ThirdwebClient; + layout: "row" | "column"; }) { return ( -

-
+
+

Project Wallet

@@ -292,6 +301,24 @@ export function ProjectWalletSectionUI(props: { thirdweb API

+ {props.layout === "row" && ( +
+ +
+ )}
{props.projectWallet ? ( @@ -318,6 +345,7 @@ export function ProjectWalletSection(props: { teamSlug: string; projectWallet: ProjectWalletSummary | undefined; client: ThirdwebClient; + layout: "row" | "column"; }) { return ( ); } diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx index 3226572d485..ff2b14933a3 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx @@ -119,7 +119,7 @@ export default async function ProjectOverviewPage(props: PageProps) { isProjectIcon: true, icon: () => ( @@ -130,30 +130,44 @@ export default async function ProjectOverviewPage(props: PageProps) { actions: null, }} > - - -
- {isActive ? ( -
- - + +
+ + +
) : ( - +
+ + } + /> +
)} diff --git a/packages/service-utils/src/core/services.ts b/packages/service-utils/src/core/services.ts index ffaead9ae84..bdcb373370d 100644 --- a/packages/service-utils/src/core/services.ts +++ b/packages/service-utils/src/core/services.ts @@ -4,7 +4,7 @@ export const SERVICE_DEFINITIONS = { actions: [], description: "Bundler & Paymaster services", name: "bundler", - title: "Account Abstraction", + title: "Gas Sponsorship", }, chainsaw: { // all actions allowed @@ -18,7 +18,7 @@ export const SERVICE_DEFINITIONS = { actions: [], description: "E-mail and social login wallets for easy web3 onboarding", name: "embeddedWallets", - title: "Wallets", + title: "User Wallets", }, engineCloud: { @@ -27,14 +27,14 @@ export const SERVICE_DEFINITIONS = { description: "Transaction API and Server wallets with high transaction throughput and low latency", name: "engineCloud", - title: "Transactions", + title: "Server Wallets", }, insight: { // all actions allowed actions: [], description: "Indexed data for any EVM chain", name: "insight", - title: "Insight", + title: "Indexer", }, nebula: { // all actions allowed @@ -42,7 +42,7 @@ export const SERVICE_DEFINITIONS = { description: "Advanced blockchain reasoning and execution capabilities with AI", name: "nebula", - title: "thirdweb AI", + title: "AI", }, pay: { // all actions allowed @@ -50,7 +50,7 @@ export const SERVICE_DEFINITIONS = { description: "Bridge, swap, and purchase cryptocurrencies and execute transactions with any fiat or tokens via cross-chain routing", name: "pay", - title: "Payments", + title: "Bridge", }, relayer: { // all actions allowed