-
Notifications
You must be signed in to change notification settings - Fork 559
[SDK] Add enableCard prop to control fiat payment visibility #7465
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
Adds enableCard prop to BuyWidget, CheckoutWidget, and TransactionWidget components to allow hiding the "Buy with card" fiat payment option. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: abd2103 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 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 |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
## Walkthrough
A new optional `paymentMethods` property was introduced to the `BuyWidget`, `CheckoutWidget`, `TransactionWidget`, `BridgeOrchestrator`, `PaymentSelection`, and `WalletFiatSelection` components. This property accepts an array containing `"crypto"` and/or `"card"` to control which payment methods are available and conditionally render payment options in the UI. Additionally, playground UI components were updated to allow selecting payment methods, and the `PayEmbed` component refined logic for determining enabled payment methods based on flags.
## Changes
| Files/Groups | Change Summary |
|-------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| .changeset/dull-breads-start.md | Added a changeset describing the addition of the `paymentMethods` prop to BuyWidget, CheckoutWidget, and TransactionWidget. |
| packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx<br>packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx<br>packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx | Added optional `paymentMethods` prop to widget props interfaces/types and passed it to BridgeOrchestrator. |
| packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx | Added optional `paymentMethods` prop with default `["crypto", "card"]` to orchestrator props and passed it to PaymentSelection during method selection. |
| packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx | Added optional `paymentMethods` prop with default `["crypto", "card"]` to selection props and passed it to WalletFiatSelection; renamed local variable to avoid conflicts. |
| packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx | Added optional `paymentMethods` prop; conditionally renders "Pay with Crypto" and "Pay with Card" UI based on presence in `paymentMethods`; changed heading text to "Pay with Card." |
| packages/thirdweb/src/react/web/ui/PayEmbed.tsx | Refined logic for determining `paymentMethods` prop based on `buyWithFiat` and `buyWithCrypto` flags; removed extraneous JSDoc newline. |
| apps/playground-web/src/app/connect/pay/components/CodeGen.tsx | Extended JSX code generation to conditionally include `paymentMethods` prop if present in options. |
| apps/playground-web/src/app/connect/pay/components/types.ts | Added required `paymentMethods` property to `payOptions` type; updated import statements for `Chain` and `Address`. |
| apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx | Added UI checkboxes for selecting "Crypto" and "Card" payment methods in "buy" and "checkout" widget modes; updated `payOptions.paymentMethods` accordingly. |
| apps/playground-web/src/app/connect/pay/embed/RightSection.tsx | Passed `paymentMethods` prop from `payOptions` to `BuyWidget`, `CheckoutWidget`, and `TransactionWidget`. |
| apps/playground-web/src/app/connect/pay/embed/page.tsx | Added default `paymentMethods` array with `["crypto", "card"]` to `defaultConnectOptions` in `payOptions`. |
## Sequence Diagram(s)
```mermaid
sequenceDiagram
participant PayEmbed
participant Widget (Buy/Checkout/Transaction)
participant BridgeOrchestrator
participant PaymentSelection
participant WalletFiatSelection
PayEmbed->>Widget: Render with paymentMethods (based on payOptions.buyWithFiat and buyWithCrypto)
Widget->>BridgeOrchestrator: Pass paymentMethods prop
BridgeOrchestrator->>PaymentSelection: Pass paymentMethods prop
PaymentSelection->>WalletFiatSelection: Pass paymentMethods prop
WalletFiatSelection-->>WalletFiatSelection: Conditionally render crypto/card payment UI based on paymentMethods Possibly related PRs
Suggested reviewers
|
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. |
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 (2)
packages/thirdweb/src/react/web/ui/PayEmbed.tsx (2)
362-362
: Consider simplifying the conditional logic.The current logic works correctly but can be simplified for better readability:
- enableCard={props.payOptions?.buyWithFiat === false ? false : true} + enableCard={props.payOptions?.buyWithFiat !== false}This achieves the same result (enableCard is false only when buyWithFiat is explicitly false) with more concise code.
Also applies to: 381-381, 398-398
519-522
: Unrelated formatting change detected.The autoConnect type definition formatting appears to be an unrelated change. While the formatting is fine, it's generally better to keep formatting changes separate from functional changes for cleaner commit history.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
.changeset/dull-breads-start.md
(1 hunks)packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/PayEmbed.tsx
(4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
packages/thirdweb/src/react/web/ui/PayEmbed.tsx
packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
.changeset/dull-breads-start.md (1)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (3)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Keep components pure by fetching data outside (in server components or hooks) and passing it down via props.
packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Keep components pure by fetching data outside (in server components or hooks) and passing it down via props.
packages/thirdweb/src/react/web/ui/PayEmbed.tsx (3)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Keep components pure by fetching data outside (in server components or hooks) and passing it down via props.
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx (3)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (1)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
🧬 Code Graph Analysis (1)
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx (2)
packages/thirdweb/src/react/web/ui/components/buttons.tsx (1)
Button
(19-140)packages/thirdweb/src/react/web/ui/ConnectWallet/icons/CreditCardIcon.tsx (1)
CreditCardIcon
(6-24)
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Socket Security: Pull Request Alerts
- GitHub Check: Analyze (javascript)
🔇 Additional comments (13)
.changeset/dull-breads-start.md (1)
1-6
: LGTM!The changeset properly documents the addition of the
enableCard
prop to the three widget components with an appropriate patch-level version bump.packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx (2)
164-168
: LGTM!The
enableCard
prop is properly documented with clear JSDoc comments and follows the existing pattern for optional boolean props in the interface.
391-391
: LGTM!The
enableCard
prop is correctly passed down to theBridgeOrchestrator
component, maintaining the prop flow through the component hierarchy.packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx (2)
170-174
: LGTM!The
enableCard
prop implementation is consistent with the pattern established inBuyWidget
, with identical documentation and typing.
354-354
: LGTM!The prop forwarding to
BridgeOrchestrator
maintains consistency with other widget components.packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx (2)
173-177
: LGTM!The
enableCard
prop implementation maintains perfect consistency with the other widget components, following the same documentation and typing patterns.
413-413
: LGTM!The prop forwarding completes the consistent pattern across all three widget components.
packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx (3)
117-120
: LGTM!The
enableCard
prop is properly added to the interface with consistent documentation that matches the widget components.
135-135
: LGTM!The
enableCard
parameter is correctly added to the function signature, maintaining consistency with the interface.
280-280
: LGTM!The
enableCard
prop is appropriately passed toPaymentSelection
during themethodSelection
state, which is the correct point in the flow where payment method choices are presented.packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx (1)
75-78
: Well-implemented prop threading.The enableCard prop is properly:
- Typed as optional boolean with clear JSDoc documentation
- Added to function parameters
- Passed down to WalletFiatSelection component
The implementation follows React best practices for prop drilling.
Also applies to: 98-98, 257-257
packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx (2)
24-24
: Proper prop definition with sensible default.The enableCard prop is correctly typed as optional boolean with a default value of
true
, which makes sense since card payments should be available by default unless explicitly disabled.Also applies to: 33-33
131-174
: Excellent conditional rendering and improved UX.The implementation correctly:
- Conditionally renders the entire card payment section based on
enableCard
- Updates the user-facing text from "Pay with Fiat" to "Pay with Card" for better clarity
- Maintains consistent styling and layout with existing UI patterns
- Reuses the existing
CreditCardIcon
component appropriatelyThe text change to "Pay with Card" is more intuitive for end users than the technical term "fiat".
size-limit report 📦
|
/** | ||
* Whether to enable the "Buy with card" (fiat payment) option | ||
*/ | ||
enableCard?: boolean; |
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.
What if we do an array instead of litterals
Crypt, card (later we'll have more like ACH, exchange)
Codecov ReportAttention: Patch coverage is
❌ Your patch status has failed because the patch coverage (0.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #7465 +/- ##
==========================================
- Coverage 51.99% 51.93% -0.06%
==========================================
Files 949 949
Lines 64081 64155 +74
Branches 4229 4229
==========================================
+ Hits 33318 33319 +1
- Misses 30656 30729 +73
Partials 107 107
🚀 New features to boost your workflow:
|
Replace boolean enableCard prop with paymentMethods array that accepts ["crypto", "card"] literals. This provides more flexibility for controlling available payment options in BuyWidget, CheckoutWidget, and TransactionWidget. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
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 (1)
.changeset/dull-breads-start.md (1)
5-5
: Prop name in description conflicts with PR objective (enableCard
vspaymentMethods
).The PR description and objectives talk about introducing an
enableCard
boolean, while this changeset message documents a newpaymentMethods
array prop.
Please double-check the actual implementation and update the changeset so the wording (and therefore the generated release notes) matches the real API surface.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
.changeset/dull-breads-start.md
(1 hunks)packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/PayEmbed.tsx
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
- packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
- packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
- packages/thirdweb/src/react/web/ui/PayEmbed.tsx
🧰 Additional context used
🧠 Learnings (1)
.changeset/dull-breads-start.md (1)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
⏰ Context from checks skipped due to timeout of 90000ms (7)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Unit Tests
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
@@ -393,6 +395,7 @@ export function PayEmbed(props: PayEmbedProps) { | |||
image={metadata?.image} | |||
onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} | |||
theme={theme} | |||
paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} |
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.
Is there a way to do fiat only?
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx
(1 hunks)apps/playground-web/src/app/connect/pay/components/types.ts
(2 hunks)apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx
(4 hunks)apps/playground-web/src/app/connect/pay/embed/RightSection.tsx
(3 hunks)apps/playground-web/src/app/connect/pay/embed/page.tsx
(1 hunks)packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
(3 hunks)packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
(5 hunks)packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
(2 hunks)packages/thirdweb/src/react/web/ui/PayEmbed.tsx
(3 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/playground-web/src/app/connect/pay/embed/page.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx
- packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx
- packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx
- packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx
- packages/thirdweb/src/react/web/ui/PayEmbed.tsx
🧰 Additional context used
📓 Path-based instructions (3)
`**/components/*`: Add 'className' to the root element of every component for external overrides. Place the file close to its feature: 'feature/components/MyComponent.tsx'.
**/components/*
: Add 'className' to the root element of every component for external overrides.
Place the file close to its feature: 'feature/components/MyComponent.tsx'.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx
apps/playground-web/src/app/connect/pay/components/types.ts
`**/components/@([A-Z][A-Za-z0-9]*)@(\.tsx|\.client\.tsx)`: Name files after the component in PascalCase; append '.client.tsx' when interactive.
**/components/@([A-Z][A-Za-z0-9]*)@(\.tsx|\.client\.tsx)
: Name files after the component in PascalCase; append '.client.tsx' when interactive.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx
apps/playground-web/src/app/connect/pay/embed/RightSection.tsx
apps/playground-web/src/app/connect/pay/components/types.ts
apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx
🧠 Learnings (4)
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx (1)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Accept a typed 'props' object and export a named function for each component to improve type safety and clarity.
apps/playground-web/src/app/connect/pay/embed/RightSection.tsx (1)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
apps/playground-web/src/app/connect/pay/components/types.ts (5)
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: UI primitives should be imported from @/components/ui/*.
apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: UI primitives should be imported from @/components/ui/*.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Reuse core UI primitives and avoid re-implementing common elements like buttons, cards, or modals.
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/playground-web/src/app/connect/pay/components/CodeGen.tsx (1)
76-76
: LGTM! Conditional prop generation is well implemented.The logic correctly checks for both existence and non-empty array before including the
paymentMethods
prop in the generated JSX. UsingJSON.stringify
is appropriate for code generation, and the formatting maintains readability.apps/playground-web/src/app/connect/pay/embed/RightSection.tsx (1)
63-63
: LGTM! Consistent prop passing across all widget types.The
paymentMethods
prop is correctly passed to all three widget components (BuyWidget
,CheckoutWidget
, andTransactionWidget
) following the same pattern as other props. This maintains consistency in the implementation.Also applies to: 85-85, 100-100
apps/playground-web/src/app/connect/pay/components/types.ts (2)
1-3
: LGTM! Improved import specificity.Moving to more specific imports (
"thirdweb/chains"
forChain
and"thirdweb/utils"
forAddress
) is a good practice that helps with tree-shaking and makes dependencies clearer.
27-27
: LGTM! Well-defined type constraint for payment methods.The
paymentMethods
type correctly constrains the array to only contain"crypto"
or"card"
values, ensuring type safety and preventing invalid payment method configurations.
{/* Payment Methods */} | ||
<div className="flex flex-col gap-3 pt-4"> | ||
<Label>Payment Methods</Label> | ||
<div className="flex gap-4"> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes( | ||
"crypto", | ||
)} | ||
id={cryptoPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
"crypto", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cryptoPaymentId}>Crypto</Label> | ||
</div> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes("card")} | ||
id={cardPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
"card", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cardPaymentId}>Card</Label> | ||
</div> | ||
</div> | ||
</div> |
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.
🛠️ Refactor suggestion
Eliminate code duplication by extracting payment methods UI.
The payment methods selection UI and logic is duplicated between the buy and checkout sections. This violates the DRY principle and makes maintenance harder.
Consider extracting this into a reusable component:
function PaymentMethodsSelector({
paymentMethods,
onPaymentMethodsChange,
cryptoId,
cardId
}: {
paymentMethods: ("crypto" | "card")[];
onPaymentMethodsChange: (methods: ("crypto" | "card")[]) => void;
cryptoId: string;
cardId: string;
}) {
const handleMethodChange = (method: "crypto" | "card", checked: boolean) => {
const newMethods = checked
? [...new Set([...paymentMethods, method])]
: paymentMethods.filter(m => m !== method);
onPaymentMethodsChange(newMethods);
};
return (
<div className="flex flex-col gap-3">
<Label>Payment Methods</Label>
<div className="flex gap-4">
<div className="flex items-center space-x-2">
<Checkbox
checked={paymentMethods.includes("crypto")}
id={cryptoId}
onCheckedChange={(checked) => handleMethodChange("crypto", !!checked)}
/>
<Label htmlFor={cryptoId}>Crypto</Label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
checked={paymentMethods.includes("card")}
id={cardId}
onCheckedChange={(checked) => handleMethodChange("card", !!checked)}
/>
<Label htmlFor={cardId}>Card</Label>
</div>
</div>
</div>
);
}
This approach also simplifies the checkbox change logic by using Set
to prevent duplicates naturally.
Also applies to: 315-372
🤖 Prompt for AI Agents
In apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx around lines
168 to 225, the payment methods UI and logic are duplicated, violating the DRY
principle. Extract this repeated UI and logic into a reusable
PaymentMethodsSelector component that accepts paymentMethods,
onPaymentMethodsChange, cryptoId, and cardId as props. Implement a single
handler inside this component to manage checkbox changes using a Set to avoid
duplicates. Replace the duplicated code blocks with this new component and apply
the same refactor to lines 315 to 372.
const cryptoPaymentId = useId(); | ||
const cardPaymentId = useId(); |
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.
ID collision issue: Generate unique IDs for each section.
The same checkbox IDs (cryptoPaymentId
, cardPaymentId
) are being reused in both the "buy" and "checkout" sections, which violates the requirement that DOM IDs be unique and could cause accessibility issues.
Generate separate IDs for each section:
const cryptoPaymentId = useId();
const cardPaymentId = useId();
+ const cryptoPaymentCheckoutId = useId();
+ const cardPaymentCheckoutId = useId();
Then use the checkout-specific IDs in the checkout section (lines 324, 349).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const cryptoPaymentId = useId(); | |
const cardPaymentId = useId(); | |
const cryptoPaymentId = useId(); | |
const cardPaymentId = useId(); | |
const cryptoPaymentCheckoutId = useId(); | |
const cardPaymentCheckoutId = useId(); |
🤖 Prompt for AI Agents
In apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx around lines 57
to 58, the IDs cryptoPaymentId and cardPaymentId are reused in both "buy" and
"checkout" sections causing ID collisions. To fix this, generate separate unique
IDs for the checkout section, for example checkoutCryptoPaymentId and
checkoutCardPaymentId, and replace the IDs used in the checkout section at lines
324 and 349 with these new IDs to ensure all DOM IDs are unique.
Adds enableCard prop to BuyWidget, CheckoutWidget, and TransactionWidget components to allow hiding the "Buy with card" fiat payment option.
🤖 Generated with Claude Code
PR-Codex overview
This PR introduces a
paymentMethods
property across various components to control available payment options, allowing users to select between "crypto" and "card". This enhancement improves flexibility in payment processing.Detailed summary
paymentMethods
property toBuyWidget
,CheckoutWidget
, andTransactionWidget
.paymentMethods: ("crypto" | "card")[]
.PayEmbed
to conditionally render payment methods based on props.LeftSection
for selecting payment methods.WalletFiatSelection
to handle payment method display based on selected options.Summary by CodeRabbit