-
Notifications
You must be signed in to change notification settings - Fork 630
[MNY-343] Add checkout widget iframe #8578
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
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: fdd2557 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
WalkthroughAdds a Checkout Widget iframe feature with CSP headers and a public env var; new query parsing and currency-validation utilities; embed client, layout, and page for the checkout iframe; refactors bridge widget to use utilities; removes inline fiat display from buy button; and updates smart-wallet test suites to be skipped/modified. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant NextJS as Next.js Page
participant Providers as BridgeProviders
participant Thirdweb as Thirdweb Client/Widget
Note over Browser,NextJS: Request to /bridge/checkout-widget with query params
Browser->>NextJS: GET /bridge/checkout-widget?...
NextJS->>NextJS: parseQueryParams + isValidCurrency
alt invalid or missing required params
NextJS-->>Browser: render error UI
else valid params
NextJS->>Providers: initialize (uses NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID)
Providers->>Thirdweb: create configured iframe client
NextJS-->>Browser: render CheckoutWidgetEmbed (client component)
Browser->>Thirdweb: widget initializes (iframe)
Thirdweb-->>Browser: postMessage(success/error) [source: "checkout-widget"]
Browser->>NextJS: (parent) receives postMessage event
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 3 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
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.
Actionable comments posted: 0
🧹 Nitpick comments (5)
apps/dashboard/src/app/bridge/checkout-widget/layout.tsx (1)
15-26: Consider adding basic<head>elements for proper document structure.The layout renders
<html>and<body>but omits a<head>with essential meta tags like<meta charset="utf-8">and<meta name="viewport">. Even for iframe embeds, these ensure consistent rendering across browsers.🔎 Suggested improvement
return ( <html lang="en" suppressHydrationWarning> + <head> + <meta charSet="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + </head> <body className={cn( "min-h-dvh bg-background font-sans antialiased flex flex-col", fontSans.variable, )} > {children} </body> </html> );apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
3-10: Consider simplifying the type guard and reordering declarations.The function works correctly, but could be more concise. Also, moving
VALID_CURRENCIESbefore its usage improves readability.🔎 Suggested simplification
import type { SupportedFiatCurrency } from "thirdweb/react"; +const VALID_CURRENCIES: Record<SupportedFiatCurrency, true> = { + USD: true, + EUR: true, + // ... rest of currencies +}; + export function isValidCurrency( currency: string, ): currency is SupportedFiatCurrency { - if (currency in VALID_CURRENCIES) { - return true; - } - return false; + return currency in VALID_CURRENCIES; } - -const VALID_CURRENCIES: Record<SupportedFiatCurrency, true> = { - // ... -};apps/dashboard/src/app/bridge/checkout-widget/page.tsx (2)
1-14: Missingimport "server-only";directive.Per coding guidelines, server component files should start with
import "server-only";to prevent accidental client bundling. This is an async server component that reads searchParams.🔎 Proposed fix
import type { Metadata } from "next"; +import "server-only"; import "@workspace/ui/global.css";
45-49: Variabletitleshadows module-level constant.The local variable
titleon line 45 shadows the module-leveltitleconstant defined on line 16. This could cause confusion. Consider renaming toproductTitleor similar.🔎 Proposed fix
- const title = parseQueryParams(searchParams.title, (v) => v); + const productTitle = parseQueryParams(searchParams.title, (v) => v);Then update the usage on line 119:
- name={title} + name={productTitle}apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
49-50: ESLint disable comment.The
// eslint-disable-next-line no-restricted-syntaxsuggestsdefineChainusage is restricted. If this is intentional for the widget context, the comment should briefly explain why the exception is needed.- // eslint-disable-next-line no-restricted-syntax + // eslint-disable-next-line no-restricted-syntax -- defineChain needed for dynamic chain resolution from query params const chain = useMemo(() => defineChain(chainId), [chainId]);
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.changeset/short-wasps-show.md(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/src/@/constants/public-envs.ts(1 hunks)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts(1 hunks)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/layout.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/page.tsx(1 hunks)apps/dashboard/src/app/bridge/widget/page.tsx(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsx
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsx
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsx
apps/dashboard/**/layout.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/layout.{ts,tsx}: ReuseSidebarLayoutorFullWidthSidebarLayoutfrom@/components/blocks/SidebarLayoutfor all layouts
Export default async functions without'use client';in server components; they run on the Node edge
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
apps/dashboard/src/app/bridge/checkout-widget/layout.tsxapps/dashboard/src/@/constants/public-envs.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
apps/dashboard/**/page.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use the
containerclass with amax-w-7xlcap for consistent page width
Files:
apps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/widget/page.tsx
apps/dashboard/**/*.client.tsx
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.client.tsx: Name component files after the component in PascalCase; append.client.tsxwhen the component is interactive
Client components must start with'use client';directive before imports
Files:
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
🧬 Code graph analysis (3)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (5)
apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
CheckoutWidgetEmbed(10-71)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)apps/dashboard/src/app/bridge/(general)/components/client/Providers.client.tsx (1)
BridgeProviders(9-42)
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (2)
apps/dashboard/src/@/constants/thirdweb.server.ts (1)
getConfiguredThirdwebClient(26-97)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)
apps/dashboard/src/app/bridge/widget/page.tsx (2)
apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (15)
apps/dashboard/next.config.ts (1)
164-181: LGTM! CSP headers correctly extend to checkout widget routes.The configuration mirrors the existing
/bridge/widgetroutes and properly appliesEmbedContentSecurityPolicywithframe-ancestors *for iframe embedding support.packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx (1)
164-166: LGTM! Clean simplification of button label rendering.The change removes the redundant fiat price display from the button, which aligns with the changeset description. The price is already displayed prominently in the FiatValue component above (lines 82-91).
.changeset/short-wasps-show.md (1)
1-5: LGTM! Changeset correctly documents the UI change.apps/dashboard/src/@/constants/public-envs.ts (1)
47-49: LGTM! New environment constant follows existing patterns.The constant mirrors
NEXT_PUBLIC_BRIDGE_IFRAME_CLIENT_IDwithout a default value, which is appropriate since the consuming code will throw if the value is missing.apps/dashboard/src/app/bridge/widget/page.tsx (2)
37-74: LGTM! Clean refactor to centralized query parameter utilities.The migration to
parseQueryParamswithonlyNumber,onlyAddress, andisValidCurrencyvalidators improves consistency and type safety across the bridge widget configuration. The pattern is reusable for the new checkout widget flow.
120-138: LGTM! Proper guard for required environment variable.Throwing early when
NEXT_PUBLIC_BRIDGE_IFRAME_CLIENT_IDis missing provides clear feedback during development/deployment rather than failing silently.apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (2)
3-11: LGTM!Clean, well-typed generic utility function with proper handling of the union type. The function correctly processes only string values and returns
undefinedfor arrays and undefined inputs.
13-15: LGTM!Both validators are concise and correctly implemented.
onlyAddressleverages thirdweb'sisAddresscheck, andonlyNumberproperly handles NaN cases.apps/dashboard/src/app/bridge/checkout-widget/page.tsx (4)
57-60:showThirdwebBrandingdefaults totruewhen param is missing.When
searchParams.showThirdwebBrandingisundefined,parseQueryParamsreturnsundefinedwithout calling the callback. However, when the param is present but not"false", the callback returnstrue. This means the prop will beundefinedwhen the param is absent, nottrue.If the intent is to default to
truewhen not specified, add a fallback:🔎 Proposed fix if defaulting to true is intended
const showThirdwebBranding = parseQueryParams( searchParams.showThirdwebBranding, (v) => v !== "false", - ); + ) ?? true;
134-152: Runtime error if env var is missing.The
Providersfunction throws at runtime ifNEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_IDis not set. This will crash the page for users rather than showing an error. Consider handling this more gracefully or validating at build time.Also, this function is defined inside the same file as a server component but doesn't have
"use client"directive. Since it usesBridgeProviders(a client component), React will handle this via the component boundary, but the throw will happen server-side during render.Is the intention to fail hard here, or should this show a user-friendly error similar to the invalid configuration block?
71-109: LGTM on validation and error UI.Good use of design tokens (
bg-background,bg-card,text-destructive-text,text-muted-foreground) and clear error messaging for missing required parameters.
111-131: LGTM on widget rendering.Props are correctly passed through to
CheckoutWidgetEmbed, and the layout follows the project's Tailwind-based styling conventions.apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (3)
39-47:NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_IDmay be undefined.Unlike the
Providerswrapper inpage.tsxwhich throws if the env var is missing, this component passes it directly togetConfiguredThirdwebClient. Looking at the snippet fromthirdweb.server.ts, the function falls back toNEXT_PUBLIC_DASHBOARD_CLIENT_IDor"dummy-build-client", which may not be the intended behavior for this widget.Consider adding validation or leveraging the parent's guarantee that the env var exists.
52-70: LGTM on CheckoutWidget rendering.All props are correctly passed through to the widget with appropriate types.
7-8: No issues found. The import ofgetConfiguredThirdwebClientfrom@/constants/thirdweb.serverin this client component is safe—the module contains noimport "server-only"directive, uses no Node.js-specific APIs, and handles environment variables with proper fallbacks for client-side execution.
size-limit report 📦
|
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.
Actionable comments posted: 2
🧹 Nitpick comments (5)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (3)
67-69: Remove unnecessary type assertion.Since
isValidCurrencyis a type guard that returnscurrency is SupportedFiatCurrency, the explicitas SupportedFiatCurrencycast is redundant. TypeScript already narrows the type within the ternary's true branch.🔎 Suggested simplification
const currency = parseQueryParams(searchParams.currency, (v) => - isValidCurrency(v) ? (v as SupportedFiatCurrency) : undefined, + isValidCurrency(v) ? v : undefined, );
40-40: Consider validating the amount parameter format.The
amountparameter accepts any string value without numeric validation. While downstream components may handle invalid formats, validating it here (e.g., checking for valid decimal format) would provide earlier feedback and a clearer error message to users.🔎 Optional validation approach
- const amount = parseQueryParams(searchParams.amount, (v) => v); + const amount = parseQueryParams(searchParams.amount, (v) => { + // Allow numbers with optional decimals + return /^\d+\.?\d*$/.test(v) ? v : undefined; + });Then update the error message on line 94-96 to clarify the expected format:
{!amount && ( <li> - • <InlineCode code="amount" /> - Amount to charge (e.g., "0.01") + • <InlineCode code="amount" /> - Amount to charge as a valid number (e.g., "0.01", "100") </li> )}
141-143: Review error handling: throwing during render may cause poor UX.Throwing an error during component render will trigger an error boundary (or crash the app if none exists). For a missing environment variable, consider one of these patterns:
- Show a graceful error UI instead of throwing
- Perform the check at build time or during initialization
- Use Next.js environment variable validation
This ensures users see a helpful message rather than a blank page or generic error boundary.
🔎 Alternative: graceful error UI
if (!NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID) { - throw new Error("NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID is not set"); + return ( + <div className="flex min-h-screen items-center justify-center bg-background px-4"> + <div className="max-w-md rounded-xl border bg-card p-6 text-center"> + <h2 className="mb-2 font-semibold text-destructive-text">Configuration Error</h2> + <p className="text-muted-foreground text-sm"> + Missing required environment variable: NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID + </p> + </div> + </div> + ); }apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (2)
3-11: Document the string[] handling behavior.The function silently returns
undefinedforstring[]values without processing them. While this may be intentional (Next.js query params can be arrays when the same key appears multiple times), documenting this behavior would help future maintainers understand the design choice.🔎 Suggested documentation
+/** + * Parse and transform a query parameter value. + * + * @param value - Query parameter from Next.js searchParams (string, string[], or undefined) + * @param fn - Transformation function to apply to string values + * @returns Transformed value, or undefined if value is not a string or transformation fails + * + * @remarks + * Only processes single string values. Arrays (multiple values for same key) return undefined. + */ export function parseQueryParams<T>( value: string | string[] | undefined, fn: (value: string) => T | undefined, ): T | undefined {
14-15: Consider clarifying the number validation logic.While
Number.isNaN(Number(v))works correctly, the doubleNumber()call can be unclear. Consider extracting to a const or adding a comment for readability.🔎 Slightly clearer alternative
-export const onlyNumber = (v: string) => - Number.isNaN(Number(v)) ? undefined : Number(v); +export const onlyNumber = (v: string) => { + const num = Number(v); + return Number.isNaN(num) ? undefined : num; +};
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (12)
.changeset/short-wasps-show.md(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/src/@/constants/public-envs.ts(1 hunks)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts(1 hunks)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/layout.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/page.tsx(1 hunks)apps/dashboard/src/app/bridge/widget/page.tsx(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx(1 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts(1 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/dashboard/src/app/bridge/_common/isValidCurrency.ts
- apps/dashboard/next.config.ts
- .changeset/short-wasps-show.md
- apps/dashboard/src/@/constants/public-envs.ts
- apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
- apps/dashboard/src/app/bridge/checkout-widget/layout.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Place tests alongside code:foo.ts↔foo.test.tsin the same directory
Use real function invocations with stub data in tests; avoid brittle mocks
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests
Keep tests deterministic and side-effect free
Use predefined test accounts fromtest/src/test-wallets.tsin tests
UseFORKED_ETHEREUM_CHAINfor mainnet interactions andANVIL_CHAINfor isolated tests
**/*.test.{ts,tsx}: Co-locate tests with source files using the pattern foo.ts ↔ foo.test.ts
Use real function invocations with stub data in tests; avoid brittle mocks
For network interactions in tests, use Mock Service Worker (MSW) to intercept fetch/HTTP calls, mocking only scenarios that are hard to reproduce
Keep tests deterministic and side-effect free; Vitest is pre-configured
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
apps/dashboard/**/page.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use the
containerclass with amax-w-7xlcap for consistent page width
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsxapps/dashboard/src/app/bridge/_common/parseQueryParams.ts
🧬 Code graph analysis (2)
apps/dashboard/src/app/bridge/widget/page.tsx (2)
apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (6)
apps/dashboard/src/app/bridge/widget/page.tsx (2)
metadata(18-25)Page(31-118)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
CheckoutWidgetEmbed(10-71)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)apps/dashboard/src/app/bridge/(general)/components/client/Providers.client.tsx (1)
BridgeProviders(9-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx (1)
165-165: LGTM! Simplified button content.The change removes the duplicate fiat price display from the button while keeping it visible in the price section above (lines 82-91). The button now shows the custom label or "Buy Now" fallback, which is clearer and less redundant.
apps/dashboard/src/app/bridge/widget/page.tsx (1)
37-74: LGTM! Clean refactoring to centralized parsing utilities.The migration to
parseQueryParamswithonlyAddress,onlyNumber, andisValidCurrencyvalidators consolidates the query parameter parsing logic and improves maintainability. The behavior remains equivalent while eliminating code duplication.apps/dashboard/src/app/bridge/checkout-widget/page.tsx (1)
72-109: Well-structured validation and error handling.The parameter validation logic correctly identifies missing required fields and provides a clear, user-friendly error message with specific guidance. The UI uses design tokens appropriately and lists exactly which parameters are missing.
apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (1)
13-13: Clean address validation helper.The
onlyAddressvalidator correctly leverages thirdweb'sisAddressutility for validation, providing a clear and type-safe way to parse address query parameters.
packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
Outdated
Show resolved
Hide resolved
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.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts (2)
155-174: Add explanation for skipped ERC-1271 typed data signature test.Like the test at line 122, this ERC-1271 test is skipped without explanation. If both tests share the same root cause (e.g., infrastructure requirements, known bug), consider adding a shared comment or referencing a tracking issue.
322-378: Remove FIXME or skip the test: fix the contradiction between "always fails" comment and enabled test.Line 322 contains
// FIXME: this test always fails, yet the test is enabled and will run. This creates a contradiction:
- If the test truly fails, it should be skipped with
it.skip(...)and tracked in an issue- If the test has been fixed, remove the FIXME comment
Running a test known to fail blocks CI and reduces confidence in the test suite. Resolve this by either skipping the test with documentation or removing the outdated comment if the test now passes reliably.
♻️ Duplicate comments (1)
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts (1)
122-141: Add explanation for skipped ERC-1271 signature test.This test is skipped without an inline comment explaining why. While the PR objectives mention "skipped certain ERC-1271 signature cases," future maintainers need context directly in the code.
Please add a brief comment above line 122 indicating the reason (e.g.,
// TODO: ERC-1271 verification fails post-deployment - tracking in issue #XXXXor// Skipped: requires bundler infrastructure changes).Based on past review comments flagging the same concern.
🧹 Nitpick comments (6)
apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
3-10: Consider simplifying to a single return statement.The function logic is correct, but it can be more concise.
🔎 Proposed simplification
export function isValidCurrency( currency: string, ): currency is SupportedFiatCurrency { - if (currency in VALID_CURRENCIES) { - return true; - } - return false; + return currency in VALID_CURRENCIES; }apps/dashboard/src/app/bridge/widget/page.tsx (2)
31-118: Add explicit return type to Page component.The coding guidelines require explicit function return types for TypeScript files. Consider adding
: Promise<JSX.Element>to the Page function signature.🔎 Proposed fix
-export default async function Page(props: { +export default async function Page(props: { searchParams: Promise<SearchParams>; -}) { +}): Promise<JSX.Element> {Based on coding guidelines: "Write idiomatic TypeScript with explicit function declarations and return types"
120-138: Add explicit return type to Providers component.Consider adding
: JSX.Elementto the Providers function signature for consistency with coding guidelines.🔎 Proposed fix
function Providers({ children, theme, }: { children: React.ReactNode; theme: string; -}) { +}): JSX.Element {Based on coding guidelines: "Write idiomatic TypeScript with explicit function declarations and return types"
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (3)
33-132: Add explicit return type to Page component.The coding guidelines require explicit function return types for TypeScript files. Consider adding
: Promise<JSX.Element>to the Page function signature.🔎 Proposed fix
-export default async function Page(props: { +export default async function Page(props: { searchParams: Promise<SearchParams>; -}) { +}): Promise<JSX.Element> {Based on coding guidelines: "Write idiomatic TypeScript with explicit function declarations and return types"
67-69: Remove redundant type assertion.The
as SupportedFiatCurrencycast is unnecessary because theisValidCurrencytype guard already narrows the type toSupportedFiatCurrencywhen it returns true.🔎 Proposed fix
const currency = parseQueryParams(searchParams.currency, (v) => - isValidCurrency(v) ? (v as SupportedFiatCurrency) : undefined, + isValidCurrency(v) ? v : undefined, );
134-152: Add explicit return type to Providers component.Consider adding
: JSX.Elementto the Providers function signature for consistency with coding guidelines.🔎 Proposed fix
function Providers({ children, theme, }: { children: React.ReactNode; theme: string; -}) { +}): JSX.Element {Based on coding guidelines: "Write idiomatic TypeScript with explicit function declarations and return types"
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (12)
.changeset/short-wasps-show.md(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/src/@/constants/public-envs.ts(1 hunks)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts(1 hunks)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/layout.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/page.tsx(1 hunks)apps/dashboard/src/app/bridge/widget/page.tsx(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx(1 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts(3 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- apps/dashboard/src/@/constants/public-envs.ts
- apps/dashboard/src/app/bridge/checkout-widget/layout.tsx
- apps/dashboard/src/app/bridge/_common/parseQueryParams.ts
- packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
- apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
- .changeset/short-wasps-show.md
- apps/dashboard/next.config.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
apps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/page.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use the
containerclass with amax-w-7xlcap for consistent page width
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
apps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
apps/dashboard/src/app/bridge/widget/page.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/_common/isValidCurrency.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Place tests alongside code:foo.ts↔foo.test.tsin the same directory
Use real function invocations with stub data in tests; avoid brittle mocks
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests
Keep tests deterministic and side-effect free
Use predefined test accounts fromtest/src/test-wallets.tsin tests
UseFORKED_ETHEREUM_CHAINfor mainnet interactions andANVIL_CHAINfor isolated tests
**/*.test.{ts,tsx}: Co-locate tests with source files using the pattern foo.ts ↔ foo.test.ts
Use real function invocations with stub data in tests; avoid brittle mocks
For network interactions in tests, use Mock Service Worker (MSW) to intercept fetch/HTTP calls, mocking only scenarios that are hard to reproduce
Keep tests deterministic and side-effect free; Vitest is pre-configured
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tspackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx (1)
165-165: LGTM! Clean simplification.The button label rendering is now more straightforward, removing the duplicate fiat price display while maintaining fallback behavior.
apps/dashboard/src/app/bridge/widget/page.tsx (1)
37-74: Excellent refactoring to centralized utilities!The migration to
parseQueryParamsandisValidCurrencyimproves code maintainability and eliminates duplication. The parameter parsing logic is now consistent and type-safe.apps/dashboard/src/app/bridge/checkout-widget/page.tsx (1)
72-109: Excellent validation and error handling!The required parameter validation with informative error UI provides a great user experience. The error message clearly lists missing parameters with examples, making it easy for integrators to fix configuration issues.
apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
12-36: The currency list is accurate and complete. Verified that all 23 currencies inVALID_CURRENCIESmatch theSupportedFiatCurrencytype from the thirdweb SDK exactly.
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.
Actionable comments posted: 5
♻️ Duplicate comments (3)
packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts (1)
161-161: Add explanation for skipping ERC-1271 typed data signature test.The typed data variant of the ERC-1271 signature test after deployment is now skipped, while the message signing variant (line 126) remains active. This inconsistency suggests a specific issue with typed data signing rather than a general ERC-1271 problem.
Given the existing FIXME comment pattern in this file and the past review concern about similar skipped tests, please:
- Add a comment explaining why typed data ERC-1271 verification is skipped (e.g.,
// FIXME: ERC-1271 typed data verification fails after deployment)- Create or reference a tracking issue for this known limitation
- Clarify if this is specific to v0.7 or affects other smart wallet versions
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
98-115: Security: postMessage with wildcard origin.The
sendMessageToParentfunction uses"*"as thetargetOrigin, which allows any parent window to receive these messages. If the messages contain sensitive data, this could be a security risk.Consider one of the following approaches:
If the parent origin is known at runtime, retrieve it from query params or environment and validate it:
const allowedOrigin = process.env.NEXT_PUBLIC_PARENT_ORIGIN || window.location.origin; window.parent.postMessage({ ... }, allowedOrigin);If multiple trusted origins exist, maintain an allowlist and validate:
const ALLOWED_ORIGINS = ['https://example.com', 'https://app.example.com']; const parentOrigin = new URL(document.referrer).origin; if (ALLOWED_ORIGINS.includes(parentOrigin)) { window.parent.postMessage({ ... }, parentOrigin); }If truly any origin should receive these messages, document this decision and ensure the payload contains no sensitive information beyond transaction status.
Based on the current implementation, the messages appear to contain only transaction status and error messages, which may be acceptable. However, please verify this is intentional and document the security decision.
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (1)
1-14: Add "server-only" import to prevent client bundling.According to the coding guidelines for Next.js dashboard server components, the file should start with
import "server-only";to ensure this component isn't accidentally bundled for the client.🔎 Proposed fix
+import "server-only"; import type { Metadata } from "next"; import "@workspace/ui/global.css";Based on coding guidelines: "Start server component files with
import "server-only";in Next.js"
🧹 Nitpick comments (3)
apps/dashboard/next.config.ts (1)
164-181: LGTM! CSP headers correctly configured for checkout widget embedding.The implementation properly extends the embed CSP policy to the new checkout widget routes, following the same pattern as the existing bridge widget. This will allow the checkout widget to be embedded in iframes as intended.
💡 Optional: Consider reducing duplication
The header configuration is now repeated for four routes (widget × 2, checkout-widget × 2). You could reduce duplication by extracting the repeated paths into an array:
async headers() { + const embedRoutes = [ + "/bridge/widget", + "/bridge/widget/:path*", + "/bridge/checkout-widget", + "/bridge/checkout-widget/:path*", + ]; + return [ { headers: [ ...securityHeaders, { key: "accept-ch", value: "sec-ch-viewport-width", }, ], // Apply these headers to all routes in your application. source: "/(.*)", }, - { - headers: [ - { - key: "Content-Security-Policy", - value: EmbedContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), - }, - ], - source: "/bridge/widget", - }, - { - headers: [ - { - key: "Content-Security-Policy", - value: EmbedContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), - }, - ], - source: "/bridge/widget/:path*", - }, - { - headers: [ - { - key: "Content-Security-Policy", - value: EmbedContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), - }, - ], - source: "/bridge/checkout-widget", - }, - { - headers: [ - { - key: "Content-Security-Policy", - value: EmbedContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), - }, - ], - source: "/bridge/checkout-widget/:path*", - }, + ...embedRoutes.map((source) => ({ + headers: [ + { + key: "Content-Security-Policy", + value: EmbedContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), + }, + ], + source, + })), ]; },This keeps the configuration DRY and makes future additions easier.
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
52-60: Consider validating the client ID at the component level.While
page.tsxvalidatesNEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_IDin theProviderswrapper, this component uses it directly without validation. If this component is reused elsewhere without that wrapper, it could create a client with anundefinedclientId, potentially causing runtime errors.🔎 Proposed defensive check
const client = useMemo( () => + { + if (!NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID) { + throw new Error("NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID is not configured"); + } + return getConfiguredThirdwebClient({ clientId: NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID, secretKey: undefined, teamId: undefined, - }), + }); + }, [], );apps/dashboard/src/app/bridge/checkout-widget/page.tsx (1)
45-45: Variable name shadows constant.The local variable
titleon line 45 shadows the constanttitledefined on line 16. Consider renaming the local variable to avoid confusion.🔎 Proposed fix
- const title = parseQueryParams(searchParams.title, (v) => v); + const productTitle = parseQueryParams(searchParams.title, (v) => v);And update the usage on line 119:
<CheckoutWidgetEmbed chainId={chainId} amount={amount} seller={seller} tokenAddress={tokenAddress} - name={title} + name={productTitle} description={productDescription}
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (13)
.changeset/short-wasps-show.md(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/src/@/constants/public-envs.ts(1 hunks)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts(1 hunks)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/layout.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/page.tsx(1 hunks)apps/dashboard/src/app/bridge/widget/page.tsx(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx(1 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts(3 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts(4 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- .changeset/short-wasps-show.md
- apps/dashboard/src/app/bridge/checkout-widget/layout.tsx
- apps/dashboard/src/@/constants/public-envs.ts
- packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
- apps/dashboard/src/app/bridge/_common/parseQueryParams.ts
- apps/dashboard/src/app/bridge/widget/page.tsx
- packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts
- apps/dashboard/src/app/bridge/_common/isValidCurrency.ts
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
apps/dashboard/next.config.tspackages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
apps/dashboard/next.config.tspackages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
apps/dashboard/next.config.tspackages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.tsapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Place tests alongside code:foo.ts↔foo.test.tsin the same directory
Use real function invocations with stub data in tests; avoid brittle mocks
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests
Keep tests deterministic and side-effect free
Use predefined test accounts fromtest/src/test-wallets.tsin tests
UseFORKED_ETHEREUM_CHAINfor mainnet interactions andANVIL_CHAINfor isolated tests
**/*.test.{ts,tsx}: Co-locate tests with source files using the pattern foo.ts ↔ foo.test.ts
Use real function invocations with stub data in tests; avoid brittle mocks
For network interactions in tests, use Mock Service Worker (MSW) to intercept fetch/HTTP calls, mocking only scenarios that are hard to reproduce
Keep tests deterministic and side-effect free; Vitest is pre-configured
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/*.client.tsx
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.client.tsx: Name component files after the component in PascalCase; append.client.tsxwhen the component is interactive
Client components must start with'use client';directive before imports
Files:
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
apps/dashboard/**/page.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use the
containerclass with amax-w-7xlcap for consistent page width
Files:
apps/dashboard/src/app/bridge/checkout-widget/page.tsx
🧬 Code graph analysis (2)
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (3)
apps/dashboard/src/app/bridge/(general)/components/client/UniversalBridgeEmbed.tsx (1)
bridgeWallets(11-20)apps/dashboard/src/@/constants/thirdweb.server.ts (1)
getConfiguredThirdwebClient(26-97)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (6)
apps/dashboard/src/app/bridge/widget/page.tsx (1)
metadata(18-25)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
CheckoutWidgetEmbed(23-96)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)apps/dashboard/src/app/bridge/(general)/components/client/Providers.client.tsx (1)
BridgeProviders(9-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (2)
72-109: LGTM: Clear error messaging for missing parameters.The validation logic correctly checks required parameters and provides a user-friendly error UI with specific guidance on what's missing. The error message clearly lists each missing parameter with examples.
141-143: LGTM: Environment validation in Providers wrapper.Good defensive practice to validate the required environment variable and fail fast with a clear error message if it's not configured.
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
Show resolved
Hide resolved
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
Show resolved
Hide resolved
packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
Show resolved
Hide resolved
packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
Show resolved
Hide resolved
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8578 +/- ##
==========================================
- Coverage 54.50% 53.26% -1.25%
==========================================
Files 922 922
Lines 61386 61386
Branches 4171 4026 -145
==========================================
- Hits 33459 32696 -763
- Misses 27826 28593 +767
+ Partials 101 97 -4
🚀 New features to boost your workflow:
|
Merge activity
|
<!--
## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"
If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):
## Notes for the reviewer
Anything important to call out? Be sure to also clarify these in your comments.
## How to test
Unit tests, playground, etc.
-->
<!-- start pr-codex -->
---
## PR-Codex overview
This PR focuses on enhancing the `CheckoutWidget` and related components in the `thirdweb` application, including the removal of duplicate fiat price displays, adding new environment constants, and refining query parameter parsing for improved functionality and usability.
### Detailed summary
- Removed duplicate fiat price display in `CheckoutWidget`.
- Added `NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID` constant.
- Introduced `parseQueryParams` utility for better query handling.
- Updated `CheckoutWidgetEmbed` to utilize new constants and improved query parsing.
- Added validation for required parameters in the checkout page.
- Refactored currency validation to use `isValidCurrency`.
- Modified tests to skip certain cases based on environment variables.
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Embeddable checkout widget with a dedicated checkout page/layout and a new public env var for iframe client ID.
* Content-Security-Policy headers applied to checkout widget routes.
* **Bug Fixes**
* Removed duplicate fiat price display in the checkout button.
* **Chores / Refactor**
* Centralized query-parameter parsing and currency validation; added input sanitization utilities.
* Added a patch-level changeset entry.
* **Tests**
* Marked several integration tests as skipped by default; enabled one parallel-execution test.
<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
116c326 to
fdd2557
Compare
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.
Actionable comments posted: 1
♻️ Duplicate comments (9)
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts (1)
31-31: Tests are permanently disabled without explanation.The entire smart wallet modular test suite is now unconditionally skipped, removing test coverage for critical functionality. This issue has already been raised in previous reviews.
packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts (3)
51-51: Remove the suite-level skip or add detailed explanation for why integration tests are disabled.The entire SmartWallet integration test suite is unconditionally skipped, eliminating test coverage for 14 core integration scenarios. This issue has already been raised in previous reviews.
122-122: Add a comment explaining why this test is skipped.This test for ERC-1271 signatures after deployment is skipped without explanation. This issue has already been raised in previous reviews.
322-323: Test enabled despite FIXME comment claiming it always fails.The FIXME comment at line 322 explicitly states "this test always fails," yet the test is now active (not skipped). This creates a contradiction:
- If the test genuinely always fails, it should be
it.skipto prevent CI failures- If the test has been fixed, remove the FIXME comment
🔎 Recommended fix
Either skip the test:
- // FIXME: this test always fails - it("can execute 2 tx in parallel", async () => { + it.skip("can execute 2 tx in parallel", async () => {Or remove the outdated FIXME if the test now passes:
- // FIXME: this test always fails it("can execute 2 tx in parallel", async () => {apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (3)
12-21: Extract duplicated wallet configuration to a shared module.As noted in the previous review, the
bridgeWalletsarray is duplicated fromUniversalBridgeEmbed.tsx. Extract this to a shared location like@/constants/wallets.tsto follow DRY principles.
98-115: Security: postMessage with wildcard origin.As noted in the previous review, using
"*"as thetargetOrigininpostMessageallows any parent window to receive these messages. If the messages contain sensitive data, this could be a security risk.Consider restricting the target origin to known trusted origins or document that the payload contains only non-sensitive transaction status information.
10-10: Add 'server-only' guard to thirdweb.server.ts or create a client-safe wrapper.As noted in the previous review, importing from
thirdweb.server.tsin a client component is fragile. While the current usage withsecretKey: undefinedis safe, the pattern could lead to accidental exposure of server-only code.Based on coding guidelines.
apps/dashboard/src/app/bridge/widget/page.tsx (1)
1-13: Add "server-only" import to prevent client bundling.As noted in the previous review, this server component should start with
import "server-only";to ensure it isn't accidentally bundled for the client.Based on coding guidelines.
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (1)
1-14: Add "server-only" import to prevent client bundling.As noted in the previous review, this server component should start with
import "server-only";to ensure it isn't accidentally bundled for the client.Based on coding guidelines.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (13)
.changeset/short-wasps-show.md(1 hunks)apps/dashboard/next.config.ts(1 hunks)apps/dashboard/src/@/constants/public-envs.ts(1 hunks)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts(1 hunks)apps/dashboard/src/app/bridge/_common/parseQueryParams.ts(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/layout.tsx(1 hunks)apps/dashboard/src/app/bridge/checkout-widget/page.tsx(1 hunks)apps/dashboard/src/app/bridge/widget/page.tsx(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx(1 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts(3 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts(4 hunks)packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/dashboard/src/app/bridge/_common/isValidCurrency.ts
- packages/thirdweb/src/wallets/smart/smart-wallet-integration-v07.test.ts
- apps/dashboard/src/@/constants/public-envs.ts
- apps/dashboard/src/app/bridge/checkout-widget/layout.tsx
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.test.{ts,tsx}: Place tests alongside code:foo.ts↔foo.test.tsin the same directory
Use real function invocations with stub data in tests; avoid brittle mocks
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests
Keep tests deterministic and side-effect free
Use predefined test accounts fromtest/src/test-wallets.tsin tests
UseFORKED_ETHEREUM_CHAINfor mainnet interactions andANVIL_CHAINfor isolated tests
**/*.test.{ts,tsx}: Co-locate tests with source files using the pattern foo.ts ↔ foo.test.ts
Use real function invocations with stub data in tests; avoid brittle mocks
For network interactions in tests, use Mock Service Worker (MSW) to intercept fetch/HTTP calls, mocking only scenarios that are hard to reproduce
Keep tests deterministic and side-effect free; Vitest is pre-configured
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts
packages/thirdweb/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/**/*.{ts,tsx}: Comment only ambiguous logic in SDK code; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (e.g.const { jsPDF } = await import("jspdf");)Lazy-load heavy dependencies inside async paths to keep the initial bundle lean (e.g., const { jsPDF } = await import('jspdf');)
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tspackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
packages/thirdweb/src/wallets/smart/smart-wallet-modular.test.tsapps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tspackages/thirdweb/src/wallets/smart/smart-wallet-integration.test.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxpackages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/next.config.tsapps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/app/bridge/_common/parseQueryParams.tsapps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/page.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use the
containerclass with amax-w-7xlcap for consistent page width
Files:
apps/dashboard/src/app/bridge/widget/page.tsxapps/dashboard/src/app/bridge/checkout-widget/page.tsx
apps/dashboard/**/*.client.tsx
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.client.tsx: Name component files after the component in PascalCase; append.client.tsxwhen the component is interactive
Client components must start with'use client';directive before imports
Files:
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx
🧬 Code graph analysis (2)
apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (3)
apps/dashboard/src/app/bridge/(general)/components/client/UniversalBridgeEmbed.tsx (1)
bridgeWallets(11-20)apps/dashboard/src/@/constants/thirdweb.server.ts (1)
getConfiguredThirdwebClient(26-97)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)
apps/dashboard/src/app/bridge/checkout-widget/page.tsx (5)
apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
parseQueryParams(3-11)onlyNumber(14-15)onlyAddress(13-13)apps/dashboard/src/app/bridge/_common/isValidCurrency.ts (1)
isValidCurrency(3-10)apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
CheckoutWidgetEmbed(23-96)apps/dashboard/src/@/constants/public-envs.ts (1)
NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_ID(48-49)apps/dashboard/src/app/bridge/(general)/components/client/Providers.client.tsx (1)
BridgeProviders(9-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (11)
packages/thirdweb/src/react/web/ui/Bridge/DirectPayment.tsx (1)
165-165: LGTM! Clean simplification.The direct fallback pattern is idiomatic and improves readability.
.changeset/short-wasps-show.md (1)
1-5: LGTM!The changeset entry clearly documents the patch-level UI change to remove duplicate fiat price display.
apps/dashboard/next.config.ts (1)
164-181: LGTM!The CSP headers for the checkout widget routes follow the established pattern used for the bridge widget routes. The configuration properly allows iframe embedding by using
EmbedContentSecurityPolicywithframe-ancestors *.apps/dashboard/src/app/bridge/_common/parseQueryParams.ts (3)
3-11: LGTM!The
parseQueryParamsfunction provides clean, type-safe query parameter parsing with proper handling of string, array, and undefined values.
13-13: LGTM!The
onlyAddressvalidator correctly usesisAddressfrom the thirdweb library to validate addresses.
14-15: LGTM!The
onlyNumbervalidator correctly handles number conversion and returnsundefinedfor invalid numbers.apps/dashboard/src/app/bridge/widget/page.tsx (1)
37-74: LGTM!The refactoring to use centralized
parseQueryParamsandisValidCurrencyutilities improves code organization and maintainability while preserving the original behavior.apps/dashboard/src/app/bridge/checkout-widget/CheckoutWidgetEmbed.client.tsx (1)
52-60: LGTM!The client initialization correctly uses the public environment variable and explicitly passes
undefinedfor server-only credentials.apps/dashboard/src/app/bridge/checkout-widget/page.tsx (3)
16-27: LGTM!The metadata export provides clear SEO-friendly title and description for the checkout widget page.
38-109: LGTM!The query parameter parsing and validation logic is well-structured:
- Clear separation between required and optional parameters
- Proper validation using centralized utilities
- User-friendly error UI that lists specific missing parameters with examples
134-152: LGTM!The
Providerswrapper correctly validates the required environment variable and provides a clear error message if it's missing.
| }); | ||
|
|
||
| it("should use ERC-1271 typed data signatures after deployment", async () => { | ||
| it.skip("should use ERC-1271 typed data signatures after deployment", async () => { |
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
🏁 Script executed:
#!/bin/bash
# Find and read the test file
FILE="packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts"
if [ -f "$FILE" ]; then
# Show lines 110-170 to capture both line 122 and 155
echo "=== File content from line 110 to 170 ==="
sed -n '110,170p' "$FILE"
else
echo "File not found"
fiRepository: thirdweb-dev/js
Length of output: 1889
Add explanatory comments to skipped ERC-1271 tests.
Both it.skip tests on lines 122 and 155 lack documentation explaining why they're disabled. Add inline comments describing the issue (e.g., flaky behavior, race condition after deployment) and link to any tracking issue if one exists. This helps future maintainers understand whether these tests can be re-enabled and when.
🤖 Prompt for AI Agents
In packages/thirdweb/src/wallets/smart/smart-wallet-integration.test.ts around
lines 122 and 155, both it.skip tests are missing explanatory comments; add a
short inline comment above each skipped test that explains why it is disabled
(e.g., flaky, race condition after deployment, external dependency instability),
include a link to any existing tracking/GitHub issue or ticket (or reference "no
issue filed" if none), and note the date and owner/author who skipped it so
maintainers can reassess later.

PR-Codex overview
This PR focuses on enhancing the
CheckoutWidgetand related components by removing redundant UI elements, introducing new constants, and improving the handling of query parameters for better validation and functionality in the checkout process.Detailed summary
CheckoutWidget.NEXT_PUBLIC_CHECKOUT_IFRAME_CLIENT_IDconstant.parseQueryParamsutility for better parameter handling.isValidCurrencyfunction to validate currencies.CheckoutWidgetEmbedto use new constants and improved logic.Summary by CodeRabbit
New Features
Bug Fixes
Chores / Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.