-
Notifications
You must be signed in to change notification settings - Fork 619
[Dashboard] Add x402 payments section #8394
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| "use client"; | ||
| import { Badge } from "@workspace/ui/components/badge"; | ||
| import { | ||
| BookTextIcon, | ||
| BoxIcon, | ||
|
|
@@ -76,9 +77,13 @@ export function ProjectSidebarLayout(props: { | |
| group: "Monetize", | ||
| links: [ | ||
| { | ||
| href: `${props.layoutPath}/payments`, | ||
| href: `${props.layoutPath}/x402`, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainEnsure redirect from old The route change from 🏁 Script executed: #!/bin/bash
# Description: Check for redirect configuration or middleware handling the old /payments route
# Look for redirect configurations in Next.js config or middleware
fd -e js -e ts "next.config|middleware" apps/dashboard/ --exec cat {}
# Search for any redirect/rewrite logic mentioning payments or x402
rg -n "payments.*x402|redirect.*payments" apps/dashboard/srcLength of output: 14154 🏁 Script executed: #!/bin/bash
# Find the redirects configuration file
fd -type f -name "redirects.*" apps/dashboard/ 2>/dev/null
# Look for the actual redirects file content
find apps/dashboard -name "redirects.*" -exec cat {} \;
# Verify x402 route exists
fd -type f "x402" apps/dashboard/src/app 2>/dev/null || echo "No x402 directory found"
# Look for any x402 references in the file system
fd -path "*x402*" apps/dashboard/src/app 2>/dev/null
# Check if the payments route still exists
fd -path "*payments*" apps/dashboard/src/app 2>/dev/nullLength of output: 11780 🏁 Script executed: #!/bin/bash
# Search for all x402 references in the codebase
rg -n "x402" apps/dashboard/src --type ts --type tsx
# Check the ProjectSidebarLayout file to understand context
fd -type f "ProjectSidebarLayout.tsx" apps/dashboard/src -exec cat {} \;
# Look for monetize or payments route structure
fd -path "*/sidebar/*" -type d apps/dashboard/src/app | head -20Length of output: 367 🏁 Script executed: #!/bin/bash
# Search for x402 references - rg syntax for language type
rg "x402" apps/dashboard/src -g "*.ts" -g "*.tsx"
# Get ProjectSidebarLayout file - search and display
find apps/dashboard/src -name "ProjectSidebarLayout.tsx" -exec cat {} \;
# Check sidebar routes structure
find apps/dashboard/src/app -path "*/sidebar/*" -name "page.tsx" | head -20Length of output: 7085 🏁 Script executed: #!/bin/bash
# Check if old payments route still exists in the app directory
find apps/dashboard/src/app -path "*/payments/page.tsx" -o -path "*/payments/layout.tsx" 2>/dev/null | grep -E "sidebar.*payments"
# Search for any /payments route references in sidebar components
rg "payments" apps/dashboard/src/app/\(app\)/team/\[team_slug\]/\[project_slug\]/\(sidebar\)/ -g "*.tsx" -g "*.ts" | grep -v node_modules | head -20
# Check the full projectPageRedirects to see if payments redirects exist
rg -A 2 "projectPageRedirects\s*=" apps/dashboard/next.config.js | head -50Length of output: 3505 🏁 Script executed: #!/bin/bash
# Get the complete redirects file content and search for payments redirects
find apps/dashboard -name "redirects.ts" -o -name "redirects.js" | xargs cat | grep -A 5 -B 5 "payments"Length of output: 1764 Add redirect from project-level The sidebar now points to {
destination: `${projectRoute}/x402/:path*`,
permanent: false,
source: `${projectRoute}/payments/:path*`,
}Additionally, consider removing or consolidating the orphaned 🤖 Prompt for AI Agents |
||
| icon: PayIcon, | ||
| label: "Payments", | ||
| label: ( | ||
| <span className="flex items-center gap-2"> | ||
| x402 <Badge>New</Badge> | ||
| </span> | ||
| ), | ||
| }, | ||
| { | ||
| href: `${props.layoutPath}/bridge`, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| "use client"; | ||
|
|
||
| import { BotIcon, ServerIcon, WalletIcon } from "lucide-react"; | ||
| import { FeatureCard } from "../payments/components/FeatureCard.client"; | ||
|
|
||
| export function QuickStartSection() { | ||
| return ( | ||
| <section> | ||
| <div className="mb-4"> | ||
| <h2 className="font-semibold text-xl tracking-tight">Quick Start</h2> | ||
| <p className="text-muted-foreground text-sm"> | ||
| Choose how to integrate x402 payments into your project. | ||
| </p> | ||
| </div> | ||
| <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> | ||
| <FeatureCard | ||
| title="Payment gate your API" | ||
| description="Make your endpoints payable with a single line of code" | ||
| icon={ServerIcon} | ||
| id="x402_server" | ||
| setupTime={2} | ||
| features={[ | ||
| "Supports 170+ chains", | ||
| "Supports 6.7k+ tokens", | ||
| "Dynamic pricing logic", | ||
| ]} | ||
| link={{ | ||
| href: "https://portal.thirdweb.com/x402/server", | ||
| label: "Get Started", | ||
| }} | ||
| /> | ||
|
|
||
| <FeatureCard | ||
| title="Let your users pay for x402 resources" | ||
| description="Handle x402 payments from any user wallet in your apps" | ||
| icon={WalletIcon} | ||
| id="x402_client" | ||
| setupTime={2} | ||
| features={[ | ||
| "Works with any wallet", | ||
| "No gas required", | ||
| "One line of code", | ||
| ]} | ||
| link={{ | ||
| href: "https://portal.thirdweb.com/x402/client", | ||
| label: "Get Started", | ||
| }} | ||
| /> | ||
|
|
||
| <FeatureCard | ||
| title="Equip your agents with x402 tools" | ||
| description="Give your AI agents a wallet and the ability to pay for any x402 resource" | ||
| icon={BotIcon} | ||
| id="x402_agents" | ||
| setupTime={2} | ||
| features={[ | ||
| "Remote MCP server", | ||
| "Low level APIs", | ||
| "Works with any AI framework", | ||
| ]} | ||
| link={{ | ||
| href: "https://portal.thirdweb.com/x402/agents", | ||
| label: "Get Started", | ||
| }} | ||
| /> | ||
| </div> | ||
| </section> | ||
|
Comment on lines
+6
to
+67
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Let QuickStartSection accept a className We need a import { BotIcon, ServerIcon, WalletIcon } from "lucide-react";
import { FeatureCard } from "../payments/components/FeatureCard.client";
+import { cn } from "@/lib/utils";
-export function QuickStartSection() {
+type QuickStartSectionProps = {
+ className?: string;
+};
+
+export function QuickStartSection({
+ className,
+}: QuickStartSectionProps): JSX.Element {
return (
- <section>
+ <section className={cn(className)}>As per coding guidelines 🤖 Prompt for AI Agents |
||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use client"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { usePathname, useSearchParams } from "next/navigation"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useDashboardRouter } from "@/lib/DashboardRouter"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { Metric } from "./MetricSwitcher"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MetricSwitcher } from "./MetricSwitcher"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function ChartMetricSwitcher() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const router = useDashboardRouter(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const pathname = usePathname(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const searchParams = useSearchParams(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const metric = (searchParams.get("metric") as Metric) || "volume"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleMetricChange = useCallback( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (newMetric: Metric) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const params = new URLSearchParams(searchParams.toString()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| params.set("metric", newMetric); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.replace(`${pathname}?${params.toString()}`, { scroll: false }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [pathname, router, searchParams], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div className="flex justify-end"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <MetricSwitcher value={metric} onChange={handleMetricChange} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Add explicit return type and className prop. Per coding guidelines, components should have explicit return types and expose a As per coding guidelines Apply this diff: +import { cn } from "@/lib/utils";
+
-export function ChartMetricSwitcher() {
+export function ChartMetricSwitcher({
+ className,
+}: {
+ className?: string;
+}): JSX.Element {
const router = useDashboardRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const metric = (searchParams.get("metric") as Metric) || "volume";
const handleMetricChange = useCallback(
(newMetric: Metric) => {
const params = new URLSearchParams(searchParams.toString());
params.set("metric", newMetric);
router.replace(`${pathname}?${params.toString()}`, { scroll: false });
},
[pathname, router, searchParams],
);
return (
- <div className="flex justify-end">
+ <div className={cn("flex justify-end", className)}>
<MetricSwitcher value={metric} onChange={handleMetricChange} />
</div>
);
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| "use client"; | ||
|
|
||
| import { | ||
| Select, | ||
| SelectContent, | ||
| SelectItem, | ||
| SelectTrigger, | ||
| SelectValue, | ||
| } from "@/components/ui/select"; | ||
|
|
||
| export type Metric = "payments" | "volume"; | ||
|
|
||
| export function MetricSwitcher(props: { | ||
| value: Metric; | ||
| onChange: (value: Metric) => void; | ||
| }) { | ||
| return ( | ||
| <div className="flex items-center gap-2"> | ||
| <span className="text-muted-foreground text-sm font-medium">Show:</span> | ||
| <Select value={props.value} onValueChange={props.onChange}> | ||
| <SelectTrigger className="w-[180px] rounded-full"> | ||
| <SelectValue /> | ||
| </SelectTrigger> | ||
| <SelectContent> | ||
| <SelectItem value="payments">Payments</SelectItem> | ||
| <SelectItem value="volume">Volume (USD)</SelectItem> | ||
| </SelectContent> | ||
| </Select> | ||
| </div> | ||
| ); | ||
| } | ||
|
Comment on lines
+13
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Expose className and type MetricSwitcher props This switcher needs a import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
+import { cn } from "@/lib/utils";
export type Metric = "payments" | "volume";
-export function MetricSwitcher(props: {
- value: Metric;
- onChange: (value: Metric) => void;
-}) {
+type MetricSwitcherProps = {
+ value: Metric;
+ onChange: (value: Metric) => void;
+ className?: string;
+};
+
+export function MetricSwitcher({
+ value,
+ onChange,
+ className,
+}: MetricSwitcherProps): JSX.Element {
return (
- <div className="flex items-center gap-2">
+ <div className={cn("flex items-center gap-2", className)}>
<span className="text-muted-foreground text-sm font-medium">Show:</span>
- <Select value={props.value} onValueChange={props.onChange}>
+ <Select value={value} onValueChange={onChange}>As per coding guidelines |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify Badge import path aligns with project conventions.
The coding guidelines specify importing UI primitives from
@/components/ui/*in dashboard apps, but this imports from@workspace/ui/components/badge. Confirm this is the correct import path for your monorepo setup.As per coding guidelines.
🏁 Script executed:
Length of output: 9832
Change Badge import from
@workspace/ui/components/badgeto@/components/ui/badge.The reviewed file is the only one in the dashboard using
@workspace/ui/components/badge; 56+ other files consistently import from@/components/ui/badge. This aligns with the coding guideline requiring imports from@/components/ui/*for dashboard UI primitives.🤖 Prompt for AI Agents