From a6b3d14a1fa1394360a2521859a0df883f44a80d Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Fri, 27 Jun 2025 14:29:59 -0700 Subject: [PATCH 1/5] [SDK] Add enableCard prop to control fiat payment visibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .changeset/dull-breads-start.md | 5 ++ .../web/ui/Bridge/BridgeOrchestrator.tsx | 7 ++ .../src/react/web/ui/Bridge/BuyWidget.tsx | 7 ++ .../react/web/ui/Bridge/CheckoutWidget.tsx | 7 ++ .../react/web/ui/Bridge/TransactionWidget.tsx | 7 ++ .../payment-selection/PaymentSelection.tsx | 7 ++ .../payment-selection/WalletFiatSelection.tsx | 81 ++++++++++--------- .../thirdweb/src/react/web/ui/PayEmbed.tsx | 11 ++- pnpm-lock.yaml | 31 ++----- 9 files changed, 95 insertions(+), 68 deletions(-) create mode 100644 .changeset/dull-breads-start.md diff --git a/.changeset/dull-breads-start.md b/.changeset/dull-breads-start.md new file mode 100644 index 00000000000..32ad6e841ba --- /dev/null +++ b/.changeset/dull-breads-start.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Adds enableCard prop to BuyWidget, CheckoutWidget, and TransactionWidget diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx index 96ba777db88..55d2142132e 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx @@ -113,6 +113,11 @@ export interface BridgeOrchestratorProps { * Quick buy amounts */ presetOptions: [number, number, number] | undefined; + + /** + * Whether to enable the "Buy with card" (fiat payment) option + */ + enableCard?: boolean; } export function BridgeOrchestrator({ @@ -127,6 +132,7 @@ export function BridgeOrchestrator({ purchaseData, paymentLinkId, presetOptions, + enableCard, }: BridgeOrchestratorProps) { // Initialize adapters const adapters = useMemo( @@ -271,6 +277,7 @@ export function BridgeOrchestrator({ onError={handleError} onPaymentMethodSelected={handlePaymentMethodSelected} receiverAddress={state.context.receiverAddress} + enableCard={enableCard} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx index 11a99b29ff7..ab7f01199e3 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx @@ -160,6 +160,12 @@ export type BuyWidgetProps = { * @hidden */ paymentLinkId?: string; + + /** + * Whether to enable the "Buy with card" (fiat payment) option. + * @default true + */ + enableCard?: boolean; }; // Enhanced UIOptions to handle unsupported token state @@ -382,6 +388,7 @@ export function BuyWidget(props: BuyWidgetProps) { purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} + enableCard={props.enableCard} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx index b25c19f0618..b0114d55831 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx @@ -166,6 +166,12 @@ export type CheckoutWidgetProps = { * @hidden */ paymentLinkId?: string; + + /** + * Whether to enable the "Buy with card" (fiat payment) option. + * @default true + */ + enableCard?: boolean; }; // Enhanced UIOptions to handle unsupported token state @@ -345,6 +351,7 @@ export function CheckoutWidget(props: CheckoutWidgetProps) { purchaseData={props.purchaseData} receiverAddress={props.seller} uiOptions={bridgeDataQuery.data.data} + enableCard={props.enableCard} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx index 293bbcc4148..472df1a5e28 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx @@ -169,6 +169,12 @@ export type TransactionWidgetProps = { * @hidden */ paymentLinkId?: string; + + /** + * Whether to enable the "Buy with card" (fiat payment) option. + * @default true + */ + enableCard?: boolean; }; // Enhanced UIOptions to handle unsupported token state @@ -404,6 +410,7 @@ export function TransactionWidget(props: TransactionWidgetProps) { purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} + enableCard={props.enableCard} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx index e193d54cbdd..01ce700051a 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx @@ -71,6 +71,11 @@ export interface PaymentSelectionProps { * Whether to include the destination token in the payment methods */ includeDestinationToken?: boolean; + + /** + * Whether to enable the "Buy with card" (fiat payment) option + */ + enableCard?: boolean; } type Step = @@ -90,6 +95,7 @@ export function PaymentSelection({ connectOptions, connectLocale, includeDestinationToken, + enableCard, }: PaymentSelectionProps) { const connectedWallets = useConnectedWallets(); const activeWallet = useActiveWallet(); @@ -248,6 +254,7 @@ export function PaymentSelection({ onConnectWallet={handleConnectWallet} onFiatSelected={handleFiatSelected} onWalletSelected={handleWalletSelected} + enableCard={enableCard} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx index c224dad027d..3710b096f67 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx @@ -21,6 +21,7 @@ interface WalletFiatSelectionProps { onWalletSelected: (wallet: Wallet) => void; onFiatSelected: () => void; onConnectWallet: () => void; + enableCard?: boolean; } export function WalletFiatSelection({ @@ -29,6 +30,7 @@ export function WalletFiatSelection({ onWalletSelected, onFiatSelected, onConnectWallet, + enableCard = true, }: WalletFiatSelectionProps) { const theme = useCustomTheme(); @@ -126,47 +128,50 @@ export function WalletFiatSelection({ - + {enableCard && ( + <> + - {/* Pay with Debit Card */} - - Pay with Fiat - + + Pay with Card + - + - + + + )} ); } diff --git a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx index a43d3346d34..d1cdc1f7085 100644 --- a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx +++ b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx @@ -359,6 +359,7 @@ export function PayEmbed(props: PayEmbedProps) { onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} theme={theme} title={metadata?.name || "Buy"} + enableCard={props.payOptions?.buyWithFiat === false ? false : true} tokenAddress={ props.payOptions.prefillBuy.token?.address as Address | undefined } @@ -377,6 +378,7 @@ export function PayEmbed(props: PayEmbedProps) { name={metadata?.name || "Checkout"} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} seller={props.payOptions.paymentInfo.sellerAddress as Address} + enableCard={props.payOptions?.buyWithFiat === false ? false : true} theme={theme} tokenAddress={ props.payOptions.paymentInfo.token?.address as Address | undefined @@ -393,6 +395,7 @@ export function PayEmbed(props: PayEmbedProps) { image={metadata?.image} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} theme={theme} + enableCard={props.payOptions?.buyWithFiat === false ? false : true} title={metadata?.name} transaction={props.payOptions.transaction} /> @@ -513,10 +516,10 @@ export type PayEmbedConnectOptions = { * ``` */ autoConnect?: - | { - timeout: number; - } - | boolean; + | { + timeout: number; + } + | boolean; /** * Metadata of the app that will be passed to connected wallet. Setting this is highly recommended. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9941f8ef40d..09ef73388f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -411,8 +411,6 @@ importers: specifier: 5.8.3 version: 5.8.3 - apps/login: {} - apps/nebula: dependencies: '@hookform/resolvers': @@ -1200,7 +1198,7 @@ importers: version: 22.14.1 '@vitest/coverage-v8': specifier: 3.2.3 - version: 3.2.3(vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.14.1)(@vitest/ui@3.2.3)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@22.14.1)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0)) + version: 3.2.3(vitest@3.2.3) typescript: specifier: 5.8.3 version: 5.8.3 @@ -1318,7 +1316,7 @@ importers: version: 4.0.0(storybook@9.0.8(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@5.0.10)) '@codspeed/vitest-plugin': specifier: 4.0.1 - version: 4.0.1(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))(vitest@3.2.3(@types/debug@4.1.12)(@types/node@24.0.3)(@vitest/ui@3.2.3)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.3)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0)) + version: 4.0.1(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))(vitest@3.2.3) '@coinbase/wallet-mobile-sdk': specifier: 1.1.2 version: 1.1.2(expo@53.0.11(@babel/core@7.27.4)(bufferutil@4.0.9)(graphql@16.11.0)(react-native@0.78.1(@babel/core@7.27.4)(@babel/preset-env@7.27.2(@babel/core@7.27.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0)(utf-8-validate@5.0.10))(react-native@0.78.1(@babel/core@7.27.4)(@babel/preset-env@7.27.2(@babel/core@7.27.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0) @@ -1369,7 +1367,7 @@ importers: version: 4.5.2(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0)) '@vitest/coverage-v8': specifier: 3.2.3 - version: 3.2.3(vitest@3.2.3(@types/debug@4.1.12)(@types/node@24.0.3)(@vitest/ui@3.2.3)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.3)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0)) + version: 3.2.3(vitest@3.2.3) '@vitest/ui': specifier: 3.2.3 version: 3.2.3(vitest@3.2.3) @@ -18332,7 +18330,7 @@ snapshots: transitivePeerDependencies: - debug - '@codspeed/vitest-plugin@4.0.1(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))(vitest@3.2.3(@types/debug@4.1.12)(@types/node@24.0.3)(@vitest/ui@3.2.3)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.3)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))': + '@codspeed/vitest-plugin@4.0.1(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))(vitest@3.2.3)': dependencies: '@codspeed/core': 4.0.1 vite: 6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0) @@ -25442,7 +25440,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@3.2.3(vitest@3.2.3(@types/debug@4.1.12)(@types/node@22.14.1)(@vitest/ui@3.2.3)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@22.14.1)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))': + '@vitest/coverage-v8@3.2.3(vitest@3.2.3)': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -25461,25 +25459,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@3.2.3(vitest@3.2.3(@types/debug@4.1.12)(@types/node@24.0.3)(@vitest/ui@3.2.3)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.3)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0))': - dependencies: - '@ampproject/remapping': 2.3.0 - '@bcoe/v8-coverage': 1.0.2 - ast-v8-to-istanbul: 0.3.3 - debug: 4.4.1(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.1.7 - magic-string: 0.30.17 - magicast: 0.3.5 - std-env: 3.9.0 - test-exclude: 7.0.1 - tinyrainbow: 2.0.0 - vitest: 3.2.3(@types/debug@4.1.12)(@types/node@24.0.3)(@vitest/ui@3.2.3)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.3)(typescript@5.8.3))(terser@5.42.0)(tsx@4.20.1)(yaml@2.8.0) - transitivePeerDependencies: - - supports-color - '@vitest/expect@3.0.9': dependencies: '@vitest/spy': 3.0.9 From 0c4e326d3a8456ef887e1f26379d28635cce10b0 Mon Sep 17 00:00:00 2001 From: gregfromstl Date: Fri, 27 Jun 2025 15:08:23 -0700 Subject: [PATCH 2/5] [SDK] Update enableCard prop to paymentMethods array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .changeset/dull-breads-start.md | 2 +- .../src/react/web/ui/Bridge/BridgeOrchestrator.tsx | 9 +++++---- packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx | 8 ++++---- .../thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx | 8 ++++---- .../src/react/web/ui/Bridge/TransactionWidget.tsx | 8 ++++---- .../web/ui/Bridge/payment-selection/PaymentSelection.tsx | 9 +++++---- .../ui/Bridge/payment-selection/WalletFiatSelection.tsx | 6 +++--- packages/thirdweb/src/react/web/ui/PayEmbed.tsx | 6 +++--- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/.changeset/dull-breads-start.md b/.changeset/dull-breads-start.md index 32ad6e841ba..387b53419da 100644 --- a/.changeset/dull-breads-start.md +++ b/.changeset/dull-breads-start.md @@ -2,4 +2,4 @@ "thirdweb": patch --- -Adds enableCard prop to BuyWidget, CheckoutWidget, and TransactionWidget +Adds paymentMethods prop to BuyWidget, CheckoutWidget, and TransactionWidget to control available payment options. Accepts an array of "crypto" and/or "card" values. diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx index 55d2142132e..021667916ae 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx @@ -115,9 +115,10 @@ export interface BridgeOrchestratorProps { presetOptions: [number, number, number] | undefined; /** - * Whether to enable the "Buy with card" (fiat payment) option + * Allowed payment methods + * @default ["crypto", "card"] */ - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; } export function BridgeOrchestrator({ @@ -132,7 +133,7 @@ export function BridgeOrchestrator({ purchaseData, paymentLinkId, presetOptions, - enableCard, + paymentMethods = ["crypto", "card"], }: BridgeOrchestratorProps) { // Initialize adapters const adapters = useMemo( @@ -277,7 +278,7 @@ export function BridgeOrchestrator({ onError={handleError} onPaymentMethodSelected={handlePaymentMethodSelected} receiverAddress={state.context.receiverAddress} - enableCard={enableCard} + paymentMethods={paymentMethods} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx index ab7f01199e3..2c917b2347f 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx @@ -162,10 +162,10 @@ export type BuyWidgetProps = { paymentLinkId?: string; /** - * Whether to enable the "Buy with card" (fiat payment) option. - * @default true + * Allowed payment methods + * @default ["crypto", "card"] */ - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; }; // Enhanced UIOptions to handle unsupported token state @@ -388,7 +388,7 @@ export function BuyWidget(props: BuyWidgetProps) { purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} - enableCard={props.enableCard} + paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx index b0114d55831..4a2fee6a0a9 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx @@ -168,10 +168,10 @@ export type CheckoutWidgetProps = { paymentLinkId?: string; /** - * Whether to enable the "Buy with card" (fiat payment) option. - * @default true + * Allowed payment methods + * @default ["crypto", "card"] */ - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; }; // Enhanced UIOptions to handle unsupported token state @@ -351,7 +351,7 @@ export function CheckoutWidget(props: CheckoutWidgetProps) { purchaseData={props.purchaseData} receiverAddress={props.seller} uiOptions={bridgeDataQuery.data.data} - enableCard={props.enableCard} + paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx index 472df1a5e28..7d6de6cdd9e 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx @@ -171,10 +171,10 @@ export type TransactionWidgetProps = { paymentLinkId?: string; /** - * Whether to enable the "Buy with card" (fiat payment) option. - * @default true + * Allowed payment methods + * @default ["crypto", "card"] */ - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; }; // Enhanced UIOptions to handle unsupported token state @@ -410,7 +410,7 @@ export function TransactionWidget(props: TransactionWidgetProps) { purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} - enableCard={props.enableCard} + paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx index 01ce700051a..ac78ce0cbaa 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx @@ -73,9 +73,10 @@ export interface PaymentSelectionProps { includeDestinationToken?: boolean; /** - * Whether to enable the "Buy with card" (fiat payment) option + * Allowed payment methods + * @default ["crypto", "card"] */ - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; } type Step = @@ -95,7 +96,7 @@ export function PaymentSelection({ connectOptions, connectLocale, includeDestinationToken, - enableCard, + paymentMethods = ["crypto", "card"], }: PaymentSelectionProps) { const connectedWallets = useConnectedWallets(); const activeWallet = useActiveWallet(); @@ -254,7 +255,7 @@ export function PaymentSelection({ onConnectWallet={handleConnectWallet} onFiatSelected={handleFiatSelected} onWalletSelected={handleWalletSelected} - enableCard={enableCard} + paymentMethods={paymentMethods} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx index 3710b096f67..495621c0c35 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx @@ -21,7 +21,7 @@ interface WalletFiatSelectionProps { onWalletSelected: (wallet: Wallet) => void; onFiatSelected: () => void; onConnectWallet: () => void; - enableCard?: boolean; + paymentMethods?: ("crypto" | "card")[]; } export function WalletFiatSelection({ @@ -30,7 +30,7 @@ export function WalletFiatSelection({ onWalletSelected, onFiatSelected, onConnectWallet, - enableCard = true, + paymentMethods = ["crypto", "card"], }: WalletFiatSelectionProps) { const theme = useCustomTheme(); @@ -128,7 +128,7 @@ export function WalletFiatSelection({ - {enableCard && ( + {paymentMethods.includes("card") && ( <> diff --git a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx index d1cdc1f7085..00492c4cc91 100644 --- a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx +++ b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx @@ -359,7 +359,7 @@ export function PayEmbed(props: PayEmbedProps) { onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} theme={theme} title={metadata?.name || "Buy"} - enableCard={props.payOptions?.buyWithFiat === false ? false : true} + paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} tokenAddress={ props.payOptions.prefillBuy.token?.address as Address | undefined } @@ -378,7 +378,7 @@ export function PayEmbed(props: PayEmbedProps) { name={metadata?.name || "Checkout"} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} seller={props.payOptions.paymentInfo.sellerAddress as Address} - enableCard={props.payOptions?.buyWithFiat === false ? false : true} + paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} theme={theme} tokenAddress={ props.payOptions.paymentInfo.token?.address as Address | undefined @@ -395,7 +395,7 @@ export function PayEmbed(props: PayEmbedProps) { image={metadata?.image} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} theme={theme} - enableCard={props.payOptions?.buyWithFiat === false ? false : true} + paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} title={metadata?.name} transaction={props.payOptions.transaction} /> From e96f4faef72e75beaeb656c940178cbd06823d51 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Sat, 28 Jun 2025 20:04:28 +1200 Subject: [PATCH 3/5] handle fiat only, add playground toggle --- .../app/connect/pay/components/CodeGen.tsx | 2 +- .../src/app/connect/pay/components/types.ts | 5 +- .../src/app/connect/pay/embed/LeftSection.tsx | 121 ++++++++++++ .../app/connect/pay/embed/RightSection.tsx | 3 + .../src/app/connect/pay/embed/page.tsx | 1 + .../web/ui/Bridge/BridgeOrchestrator.tsx | 2 +- .../src/react/web/ui/Bridge/BuyWidget.tsx | 2 +- .../react/web/ui/Bridge/CheckoutWidget.tsx | 2 +- .../react/web/ui/Bridge/TransactionWidget.tsx | 2 +- .../payment-selection/PaymentSelection.tsx | 4 +- .../payment-selection/WalletFiatSelection.tsx | 176 +++++++++--------- .../thirdweb/src/react/web/ui/PayEmbed.tsx | 29 ++- 12 files changed, 247 insertions(+), 102 deletions(-) diff --git a/apps/playground-web/src/app/connect/pay/components/CodeGen.tsx b/apps/playground-web/src/app/connect/pay/components/CodeGen.tsx index 320bea9502d..d63b58c7f23 100644 --- a/apps/playground-web/src/app/connect/pay/components/CodeGen.tsx +++ b/apps/playground-web/src/app/connect/pay/components/CodeGen.tsx @@ -73,7 +73,7 @@ function Example() { <${componentName} client={client} chain={defineChain(${options.payOptions.buyTokenChain.id})} - amount="${options.payOptions.buyTokenAmount}"${options.payOptions.buyTokenAddress ? `\n\t token="${options.payOptions.buyTokenAddress}"` : ""}${options.payOptions.sellerAddress ? `\n\t seller="${options.payOptions.sellerAddress}"` : ""}${options.payOptions.title ? `\n\t ${options.payOptions.widget === "checkout" ? "name" : "title"}="${options.payOptions.title}"` : ""}${options.payOptions.image ? `\n\t image="${options.payOptions.image}"` : ""}${options.payOptions.description ? `\n\t description="${options.payOptions.description}"` : ""}${ + amount="${options.payOptions.buyTokenAmount}"${options.payOptions.buyTokenAddress ? `\n\t token="${options.payOptions.buyTokenAddress}"` : ""}${options.payOptions.sellerAddress ? `\n\t seller="${options.payOptions.sellerAddress}"` : ""}${options.payOptions.title ? `\n\t ${options.payOptions.widget === "checkout" ? "name" : "title"}="${options.payOptions.title}"` : ""}${options.payOptions.image ? `\n\t image="${options.payOptions.image}"` : ""}${options.payOptions.description ? `\n\t description="${options.payOptions.description}"` : ""}${options.payOptions.paymentMethods && options.payOptions.paymentMethods.length > 0 ? `\n\t paymentMethods={${JSON.stringify(options.payOptions.paymentMethods)}}` : ""}${ options.payOptions.widget === "transaction" ? `\n\t transaction={claimTo({ contract: nftContract, diff --git a/apps/playground-web/src/app/connect/pay/components/types.ts b/apps/playground-web/src/app/connect/pay/components/types.ts index f784cef8b06..033cb355033 100644 --- a/apps/playground-web/src/app/connect/pay/components/types.ts +++ b/apps/playground-web/src/app/connect/pay/components/types.ts @@ -1,5 +1,6 @@ -import type { Address, Chain } from "thirdweb"; +import type { Chain } from "thirdweb/chains"; import type { ThemeOverrides } from "thirdweb/react"; +import type { Address } from "thirdweb/utils"; export type BridgeComponentsPlaygroundOptions = { theme: { @@ -22,5 +23,7 @@ export type BridgeComponentsPlaygroundOptions = { // transaction mode options transactionData?: string; // Simplified for demo; could be more complex in real implementation + + paymentMethods: ("crypto" | "card")[]; }; }; diff --git a/apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx b/apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx index bce6ea14a98..5fb7f46ecad 100644 --- a/apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx +++ b/apps/playground-web/src/app/connect/pay/embed/LeftSection.tsx @@ -13,6 +13,7 @@ import { useId, useState } from "react"; import type { Address } from "thirdweb"; import { defineChain } from "thirdweb/chains"; import { CustomRadioGroup } from "@/components/ui/CustomRadioGroup"; +import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { cn } from "../../../../lib/utils"; @@ -53,6 +54,8 @@ export function LeftSection(props: { const modalTitleIconId = useId(); const modalDescriptionId = useId(); const themeId = useId(); + const cryptoPaymentId = useId(); + const cardPaymentId = useId(); return (
@@ -161,6 +164,65 @@ export function LeftSection(props: { />
+ + {/* Payment Methods */} +
+ +
+
+ { + setOptions((v) => ({ + ...v, + payOptions: { + ...v.payOptions, + paymentMethods: checked + ? [ + ...v.payOptions.paymentMethods.filter( + (m) => m !== "crypto", + ), + "crypto", + ] + : v.payOptions.paymentMethods.filter( + (m) => m !== "crypto", + ), + }, + })); + }} + /> + +
+
+ { + setOptions((v) => ({ + ...v, + payOptions: { + ...v.payOptions, + paymentMethods: checked + ? [ + ...v.payOptions.paymentMethods.filter( + (m) => m !== "card", + ), + "card", + ] + : v.payOptions.paymentMethods.filter( + (m) => m !== "card", + ), + }, + })); + }} + /> + +
+
+
@@ -249,6 +311,65 @@ export function LeftSection(props: { /> + + {/* Payment Methods */} +
+ +
+
+ { + setOptions((v) => ({ + ...v, + payOptions: { + ...v.payOptions, + paymentMethods: checked + ? [ + ...v.payOptions.paymentMethods.filter( + (m) => m !== "crypto", + ), + "crypto", + ] + : v.payOptions.paymentMethods.filter( + (m) => m !== "crypto", + ), + }, + })); + }} + /> + +
+
+ { + setOptions((v) => ({ + ...v, + payOptions: { + ...v.payOptions, + paymentMethods: checked + ? [ + ...v.payOptions.paymentMethods.filter( + (m) => m !== "card", + ), + "card", + ] + : v.payOptions.paymentMethods.filter( + (m) => m !== "card", + ), + }, + })); + }} + /> + +
+
+
diff --git a/apps/playground-web/src/app/connect/pay/embed/RightSection.tsx b/apps/playground-web/src/app/connect/pay/embed/RightSection.tsx index 01a7be57a62..9419111cbc5 100644 --- a/apps/playground-web/src/app/connect/pay/embed/RightSection.tsx +++ b/apps/playground-web/src/app/connect/pay/embed/RightSection.tsx @@ -60,6 +60,7 @@ export function RightSection(props: { client={THIRDWEB_CLIENT} description={props.options.payOptions.description} image={props.options.payOptions.image} + paymentMethods={props.options.payOptions.paymentMethods} theme={themeObj} title={props.options.payOptions.title} tokenAddress={props.options.payOptions.buyTokenAddress} @@ -81,6 +82,7 @@ export function RightSection(props: { getDefaultImage(props.options.theme.type) } name={props.options.payOptions.title || "Your Product Name"} + paymentMethods={props.options.payOptions.paymentMethods} presetOptions={[1, 2, 3]} seller={props.options.payOptions.sellerAddress} theme={themeObj} @@ -95,6 +97,7 @@ export function RightSection(props: { client={THIRDWEB_CLIENT} description={props.options.payOptions.description} image={props.options.payOptions.image} + paymentMethods={props.options.payOptions.paymentMethods} theme={themeObj} title={props.options.payOptions.title} transaction={claimTo({ diff --git a/apps/playground-web/src/app/connect/pay/embed/page.tsx b/apps/playground-web/src/app/connect/pay/embed/page.tsx index b97ea46a286..67f24686e98 100644 --- a/apps/playground-web/src/app/connect/pay/embed/page.tsx +++ b/apps/playground-web/src/app/connect/pay/embed/page.tsx @@ -13,6 +13,7 @@ const defaultConnectOptions: BridgeComponentsPlaygroundOptions = { buyTokenChain: arbitrum, description: "", image: "", + paymentMethods: ["crypto", "card"], sellerAddress: "0x0000000000000000000000000000000000000000", title: "", transactionData: "", diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx index 021667916ae..67974983774 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BridgeOrchestrator.tsx @@ -277,8 +277,8 @@ export function BridgeOrchestrator({ }} onError={handleError} onPaymentMethodSelected={handlePaymentMethodSelected} - receiverAddress={state.context.receiverAddress} paymentMethods={paymentMethods} + receiverAddress={state.context.receiverAddress} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx index 2c917b2347f..dcb51dd8e79 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/BuyWidget.tsx @@ -384,11 +384,11 @@ export function BuyWidget(props: BuyWidgetProps) { props.onError?.(err); }} paymentLinkId={props.paymentLinkId} + paymentMethods={props.paymentMethods} presetOptions={props.presetOptions} purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} - paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx index 4a2fee6a0a9..766b1627f8c 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/CheckoutWidget.tsx @@ -347,11 +347,11 @@ export function CheckoutWidget(props: CheckoutWidgetProps) { props.onError?.(err); }} paymentLinkId={props.paymentLinkId} + paymentMethods={props.paymentMethods} presetOptions={props.presetOptions} purchaseData={props.purchaseData} receiverAddress={props.seller} uiOptions={bridgeDataQuery.data.data} - paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx index 7d6de6cdd9e..ca94be9a1d2 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionWidget.tsx @@ -406,11 +406,11 @@ export function TransactionWidget(props: TransactionWidgetProps) { props.onError?.(err); }} paymentLinkId={props.paymentLinkId} + paymentMethods={props.paymentMethods} presetOptions={props.presetOptions} purchaseData={props.purchaseData} receiverAddress={undefined} uiOptions={bridgeDataQuery.data.data} - paymentMethods={props.paymentMethods} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx index ac78ce0cbaa..0ccafe8b1c6 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx @@ -122,7 +122,7 @@ export function PaymentSelection({ ? currentStep.selectedWallet : activeWallet; const { - data: paymentMethods, + data: suitableTokenPaymentMethods, isLoading: paymentMethodsLoading, error: paymentMethodsError, } = usePaymentMethods({ @@ -269,7 +269,7 @@ export function PaymentSelection({ destinationToken={destinationToken} onBack={handleBackToWalletSelection} onPaymentMethodSelected={handlePaymentMethodSelected} - paymentMethods={paymentMethods} + paymentMethods={suitableTokenPaymentMethods} paymentMethodsLoading={paymentMethodsLoading} /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx index 495621c0c35..b75dfcf92e4 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx @@ -36,97 +36,101 @@ export function WalletFiatSelection({ return ( <> - - Pay with Crypto - - - {/* Connected Wallets */} - {connectedWallets.length > 0 && ( + {paymentMethods.includes("crypto") && ( <> - - {connectedWallets.map((wallet) => { - const account = wallet.getAccount(); - if (!account?.address) { - return null; - } - return ( - - ); - })} - - - - )} + + Pay with Crypto + + + {/* Connected Wallets */} + {connectedWallets.length > 0 && ( + <> + + {connectedWallets.map((wallet) => { + const account = wallet.getAccount(); + if (!account?.address) { + return null; + } + return ( + + ); + })} + + + + )} - {/* Connect Another Wallet */} - + + + + + + + Connect Another Wallet + + + Use a different wallet to pay + + + + + + )} {paymentMethods.includes("card") && ( <> diff --git a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx index 00492c4cc91..dc1031ee231 100644 --- a/packages/thirdweb/src/react/web/ui/PayEmbed.tsx +++ b/packages/thirdweb/src/react/web/ui/PayEmbed.tsx @@ -238,7 +238,6 @@ export type PayEmbedProps = { * }} * /> * ``` - * * You can also handle ERC20 payments by passing `erc20value` to your transaction: * * ```tsx @@ -357,9 +356,15 @@ export function PayEmbed(props: PayEmbedProps) { chain={props.payOptions.prefillBuy.chain} client={props.client} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} + paymentMethods={ + props.payOptions?.buyWithFiat === false + ? ["crypto"] + : props.payOptions?.buyWithCrypto === false + ? ["card"] + : ["crypto", "card"] + } theme={theme} title={metadata?.name || "Buy"} - paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} tokenAddress={ props.payOptions.prefillBuy.token?.address as Address | undefined } @@ -377,8 +382,12 @@ export function PayEmbed(props: PayEmbedProps) { image={metadata?.image} name={metadata?.name || "Checkout"} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} + paymentMethods={ + props.payOptions?.buyWithFiat === false + ? ["crypto"] + : ["crypto", "card"] + } seller={props.payOptions.paymentInfo.sellerAddress as Address} - paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} theme={theme} tokenAddress={ props.payOptions.paymentInfo.token?.address as Address | undefined @@ -394,8 +403,12 @@ export function PayEmbed(props: PayEmbedProps) { description={metadata?.description} image={metadata?.image} onSuccess={() => props.payOptions?.onPurchaseSuccess?.()} + paymentMethods={ + props.payOptions?.buyWithFiat === false + ? ["crypto"] + : ["crypto", "card"] + } theme={theme} - paymentMethods={props.payOptions?.buyWithFiat === false ? ["crypto"] : ["crypto", "card"]} title={metadata?.name} transaction={props.payOptions.transaction} /> @@ -516,10 +529,10 @@ export type PayEmbedConnectOptions = { * ``` */ autoConnect?: - | { - timeout: number; - } - | boolean; + | { + timeout: number; + } + | boolean; /** * Metadata of the app that will be passed to connected wallet. Setting this is highly recommended. From 633856ace2c0b74f5b21e34ea2afb192571f5959 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Sat, 28 Jun 2025 20:12:30 +1200 Subject: [PATCH 4/5] fix test --- .../core/authentication/backend.test.ts | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts b/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts index 5862ce5e0ca..d8ff83b42e9 100644 --- a/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts +++ b/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts @@ -10,60 +10,61 @@ vi.mock("../../../../utils/fetch.js"); vi.mock("./getLoginPath.js"); describe("backendAuthenticate", () => { - it("should successfully authenticate and return token", async () => { - // Mock response data - const mockResponse = { - cookieString: "mock-cookie", - token: "mock-token", - }; + it("should successfully authenticate and return token", async () => { + // Mock response data + const mockResponse = { + cookieString: "mock-cookie", + token: "mock-token", + }; - // Mock fetch implementation - const mockFetch = vi.fn().mockResolvedValue({ - json: () => Promise.resolve(mockResponse), - ok: true, - }); + // Mock fetch implementation + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve(mockResponse), + ok: true, + }); - // Mock dependencies - vi.mocked(getClientFetch).mockReturnValue(mockFetch); - vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); + // Mock dependencies + vi.mocked(getClientFetch).mockReturnValue(mockFetch); + vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); - const result = await backendAuthenticate({ - client: TEST_CLIENT, - walletSecret: "test-secret", - }); + const result = await backendAuthenticate({ + client: TEST_CLIENT, + walletSecret: "test-secret", + }); - // Verify the fetch call - expect(mockFetch).toHaveBeenCalledWith("/auth/login", { - body: stringify({ walletSecret: "test-secret" }), - headers: { - "Content-Type": "application/json", - }, - method: "POST", - }); + // Verify the fetch call + expect(mockFetch).toHaveBeenCalledWith("/auth/login", { + body: stringify({ walletSecret: "test-secret" }), + headers: { + "Content-Type": "application/json", + }, + method: "POST", + }); - // Verify response - expect(result).toEqual(mockResponse); - }); + // Verify response + expect(result).toEqual(mockResponse); + }); - it("should throw error when authentication fails", async () => { - // Mock failed fetch response - const mockFetch = vi.fn().mockResolvedValue({ - ok: false, - }); + it("should throw error when authentication fails", async () => { + // Mock failed fetch response + const mockFetch = vi.fn().mockResolvedValue({ + ok: false, + text: () => Promise.resolve("Failed to generate backend account"), + }); - // Mock dependencies - vi.mocked(getClientFetch).mockReturnValue(mockFetch); - vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); + // Mock dependencies + vi.mocked(getClientFetch).mockReturnValue(mockFetch); + vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); - // Test inputs - const args = { - client: TEST_CLIENT, - walletSecret: "test-secret", - }; + // Test inputs + const args = { + client: TEST_CLIENT, + walletSecret: "test-secret", + }; - // Verify error is thrown - await expect(backendAuthenticate(args)).rejects.toThrow( - "Failed to generate backend account", - ); - }); + // Verify error is thrown + await expect(backendAuthenticate(args)).rejects.toThrow( + "Failed to generate backend account", + ); + }); }); From abd21038f9ef0a2f4cbf205236465a079d98b149 Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Sat, 28 Jun 2025 22:14:34 +1200 Subject: [PATCH 5/5] lint --- .../core/authentication/backend.test.ts | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts b/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts index d8ff83b42e9..f34c044b3f8 100644 --- a/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts +++ b/packages/thirdweb/src/wallets/in-app/core/authentication/backend.test.ts @@ -10,61 +10,61 @@ vi.mock("../../../../utils/fetch.js"); vi.mock("./getLoginPath.js"); describe("backendAuthenticate", () => { - it("should successfully authenticate and return token", async () => { - // Mock response data - const mockResponse = { - cookieString: "mock-cookie", - token: "mock-token", - }; + it("should successfully authenticate and return token", async () => { + // Mock response data + const mockResponse = { + cookieString: "mock-cookie", + token: "mock-token", + }; - // Mock fetch implementation - const mockFetch = vi.fn().mockResolvedValue({ - json: () => Promise.resolve(mockResponse), - ok: true, - }); + // Mock fetch implementation + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve(mockResponse), + ok: true, + }); - // Mock dependencies - vi.mocked(getClientFetch).mockReturnValue(mockFetch); - vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); + // Mock dependencies + vi.mocked(getClientFetch).mockReturnValue(mockFetch); + vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); - const result = await backendAuthenticate({ - client: TEST_CLIENT, - walletSecret: "test-secret", - }); + const result = await backendAuthenticate({ + client: TEST_CLIENT, + walletSecret: "test-secret", + }); - // Verify the fetch call - expect(mockFetch).toHaveBeenCalledWith("/auth/login", { - body: stringify({ walletSecret: "test-secret" }), - headers: { - "Content-Type": "application/json", - }, - method: "POST", - }); + // Verify the fetch call + expect(mockFetch).toHaveBeenCalledWith("/auth/login", { + body: stringify({ walletSecret: "test-secret" }), + headers: { + "Content-Type": "application/json", + }, + method: "POST", + }); - // Verify response - expect(result).toEqual(mockResponse); - }); + // Verify response + expect(result).toEqual(mockResponse); + }); - it("should throw error when authentication fails", async () => { - // Mock failed fetch response - const mockFetch = vi.fn().mockResolvedValue({ - ok: false, - text: () => Promise.resolve("Failed to generate backend account"), - }); + it("should throw error when authentication fails", async () => { + // Mock failed fetch response + const mockFetch = vi.fn().mockResolvedValue({ + ok: false, + text: () => Promise.resolve("Failed to generate backend account"), + }); - // Mock dependencies - vi.mocked(getClientFetch).mockReturnValue(mockFetch); - vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); + // Mock dependencies + vi.mocked(getClientFetch).mockReturnValue(mockFetch); + vi.mocked(getLoginUrl).mockReturnValue("/auth/login"); - // Test inputs - const args = { - client: TEST_CLIENT, - walletSecret: "test-secret", - }; + // Test inputs + const args = { + client: TEST_CLIENT, + walletSecret: "test-secret", + }; - // Verify error is thrown - await expect(backendAuthenticate(args)).rejects.toThrow( - "Failed to generate backend account", - ); - }); + // Verify error is thrown + await expect(backendAuthenticate(args)).rejects.toThrow( + "Failed to generate backend account", + ); + }); });