From 2bc1f099f4ae1e9b08a0cc470489088653a4a741 Mon Sep 17 00:00:00 2001 From: Robby Uitbeijerse Date: Thu, 22 May 2025 15:43:02 +0200 Subject: [PATCH 1/5] feat: introduce supportedProviders option for fiat onramping --- .changeset/small-boxes-grow.md | 5 ++ .../hooks/connection/ConnectButtonProps.ts | 1 + .../screens/Buy/PayProviderSelection.tsx | 68 +++++++++++++++++++ .../screens/Buy/fiat/FiatScreenContent.tsx | 63 ++++++++--------- .../screens/Buy/fiat/OnRampScreen.tsx | 3 +- .../screens/Buy/fiat/Providers.tsx | 63 ++++++++--------- .../web/ui/ConnectWallet/screens/Buy/utils.ts | 4 ++ 7 files changed, 137 insertions(+), 70 deletions(-) create mode 100644 .changeset/small-boxes-grow.md create mode 100644 packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx diff --git a/.changeset/small-boxes-grow.md b/.changeset/small-boxes-grow.md new file mode 100644 index 00000000000..6126a442073 --- /dev/null +++ b/.changeset/small-boxes-grow.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Add support for filtering fiat payment providers in PayEmbed diff --git a/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts b/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts index 33df86e34ce..4a44f084e5c 100644 --- a/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts +++ b/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts @@ -98,6 +98,7 @@ export type PayUIOptions = Prettify< currency?: CurrencyMeta["shorthand"]; }; preferredProvider?: FiatProvider; + supportedProviders?: FiatProvider[]; } | false; diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx new file mode 100644 index 00000000000..0e3d16aa795 --- /dev/null +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx @@ -0,0 +1,68 @@ +import { ChevronDownIcon } from "@radix-ui/react-icons"; +import type { FiatProvider } from "src/pay/utils/commonTypes.js"; +import { iconSize, spacing } from "../../../../../core/design-system/index.js"; +import { Container } from "../../../components/basic.js"; +import { Button } from "../../../components/buttons.js"; +import { Text } from "../../../components/text.js"; +import { uppercaseFirstLetter } from "./utils.js"; + +/** + * Shows the selected payment provider based on the preferred provider OR the quoted provider. + * @internal + */ +export const PayProviderSelection = (props: { + onShowProviders: () => void; + quotedProvider?: FiatProvider; + preferredProvider?: FiatProvider; + supportedProviders: FiatProvider[]; +}) => { + const ProviderItem = ( + + + {uppercaseFirstLetter( + props.preferredProvider ?? props.quotedProvider ?? "", + )} + + {props.supportedProviders.length > 1 && ( + + )} + + ); + + return ( + + + Provider + + {props.supportedProviders.length > 1 ? ( + + ) : ( + ProviderItem + )} + + ); +}; diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx index 3b7bbc9e481..5da2fa13403 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx @@ -1,15 +1,13 @@ -import { ChevronDownIcon } from "@radix-ui/react-icons"; import { useState } from "react"; import { trackPayEvent } from "../../../../../../../analytics/track/pay.js"; import type { Chain } from "../../../../../../../chains/types.js"; import type { ThirdwebClient } from "../../../../../../../client/client.js"; import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js"; -import type { FiatProvider } from "../../../../../../../pay/utils/commonTypes.js"; import { - type Theme, - iconSize, - spacing, -} from "../../../../../../core/design-system/index.js"; + type FiatProvider, + FiatProviders, +} from "../../../../../../../pay/utils/commonTypes.js"; +import type { Theme } from "../../../../../../core/design-system/index.js"; import type { PayUIOptions } from "../../../../../../core/hooks/connection/ConnectButtonProps.js"; import { useBuyWithFiatQuote } from "../../../../../../core/hooks/pay/useBuyWithFiatQuote.js"; import { PREFERRED_FIAT_PROVIDER_STORAGE_KEY } from "../../../../../../core/utils/storage.js"; @@ -26,6 +24,7 @@ import { Button } from "../../../../components/buttons.js"; import { Text } from "../../../../components/text.js"; import { type ERC20OrNativeToken, isNativeToken } from "../../nativeToken.js"; import { EstimatedTimeAndFees } from "../EstimatedTimeAndFees.js"; +import { PayProviderSelection } from "../PayProviderSelection.js"; import { PayWithCreditCard } from "../PayWIthCreditCard.js"; import type { SelectedScreen } from "../main/types.js"; import { FiatFees } from "../swap/Fees.js"; @@ -84,6 +83,19 @@ export function FiatScreenContent(props: { : undefined, ); + const supportedProviders = (() => { + if (!buyWithFiatOptions) return [...FiatProviders]; + const options = buyWithFiatOptions?.supportedProviders ?? []; + const optionsWithPreferred = + options.length > 0 + ? new Set([ + ...(preferredProvider ? [preferredProvider] : []), + ...options, + ]) + : FiatProviders; + return Array.from(optionsWithPreferred); + })(); + const fiatQuoteQuery = useBuyWithFiatQuote( buyWithFiatOptions !== false && tokenAmount ? { @@ -98,8 +110,8 @@ export function FiatScreenContent(props: { isTestMode: buyWithFiatOptions?.testMode, purchaseData: props.payOptions.purchaseData, fromAddress: payer.account.address, - preferredProvider: preferredProvider, paymentLinkId: paymentLinkId, + preferredProvider: preferredProvider ?? "COINBASE", } : undefined, ); @@ -159,6 +171,7 @@ export function FiatScreenContent(props: { - - - Provider - - - + {/** Shows preferred or quoted provider and conditional selection */} + {/* Estimated time + View fees button */} - {step.action.charAt(0).toUpperCase() + step.action.slice(1)} + {uppercaseFirstLetter(step.action)} void; }) { @@ -21,37 +21,34 @@ export function Providers(props: { alignItems: "flex-start", }} > - {FiatProviders.map((provider) => { - return ( - ( + + - - ); - })} + {uppercaseFirstLetter(provider)} + + + + ))} ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts index 1266bdf0023..0a5650f8c0e 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts @@ -1,3 +1,7 @@ export function getBuyTokenAmountFontSize(value: string) { return value.length > 10 ? "26px" : value.length > 6 ? "34px" : "50px"; } + +export function uppercaseFirstLetter(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); +} From 1a0dde69cb2cd07eb5a0f512874b37091969dded Mon Sep 17 00:00:00 2001 From: Robby Uitbeijerse Date: Thu, 22 May 2025 15:46:04 +0200 Subject: [PATCH 2/5] chore: add comment with an explainer --- .../web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx index 0e3d16aa795..ebada391862 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx @@ -56,7 +56,7 @@ export const PayProviderSelection = (props: { From a3fbc6937eb25c4cf7a89dbfa090e83025cf76a5 Mon Sep 17 00:00:00 2001 From: Robby Uitbeijerse Date: Thu, 22 May 2025 15:59:23 +0200 Subject: [PATCH 3/5] chore: rename util --- .../ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx | 4 ++-- .../web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx | 4 ++-- .../web/ui/ConnectWallet/screens/Buy/fiat/Providers.tsx | 4 ++-- .../src/react/web/ui/ConnectWallet/screens/Buy/utils.ts | 7 ++++++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx index ebada391862..7c17e27273e 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx @@ -4,7 +4,7 @@ import { iconSize, spacing } from "../../../../../core/design-system/index.js"; import { Container } from "../../../components/basic.js"; import { Button } from "../../../components/buttons.js"; import { Text } from "../../../components/text.js"; -import { uppercaseFirstLetter } from "./utils.js"; +import { getProviderLabel } from "./utils.js"; /** * Shows the selected payment provider based on the preferred provider OR the quoted provider. @@ -25,7 +25,7 @@ export const PayProviderSelection = (props: { style={{ padding: spacing.md }} > - {uppercaseFirstLetter( + {getProviderLabel( props.preferredProvider ?? props.quotedProvider ?? "", )} diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx index eb8e9209ec7..3e76e10b970 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/OnRampScreen.tsx @@ -44,7 +44,7 @@ import { StepConnectorArrow } from "../swap/StepConnector.js"; import { WalletRow } from "../swap/WalletRow.js"; import { addPendingTx } from "../swap/pendingSwapTx.js"; import type { PayerInfo } from "../types.js"; -import { uppercaseFirstLetter } from "../utils.js"; +import { getProviderLabel } from "../utils.js"; import { StepContainer } from "./FiatSteps.js"; type OnRampScreenState = { @@ -214,7 +214,7 @@ function StepUI(props: { /> - {uppercaseFirstLetter(step.action)} + {getProviderLabel(step.action)} - {uppercaseFirstLetter(provider)} + {getProviderLabel(provider)} diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts index 0a5650f8c0e..302cbd3387b 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/utils.ts @@ -2,6 +2,11 @@ export function getBuyTokenAmountFontSize(value: string) { return value.length > 10 ? "26px" : value.length > 6 ? "34px" : "50px"; } -export function uppercaseFirstLetter(str: string) { +/** + * + * @param str accepts any string but expects a fully upppercased string / type FiatProvider + * @returns Fiat provider label to be rendered used within presentation logic + */ +export function getProviderLabel(str: string) { return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); } From 0c5260cb427fa679bc04665d9cdf652fab7aa227 Mon Sep 17 00:00:00 2001 From: Robby Uitbeijerse Date: Thu, 22 May 2025 16:17:43 +0200 Subject: [PATCH 4/5] chore: update import path for FiatProvider type --- .../web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx index 7c17e27273e..905ebcc52c1 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/PayProviderSelection.tsx @@ -1,5 +1,5 @@ import { ChevronDownIcon } from "@radix-ui/react-icons"; -import type { FiatProvider } from "src/pay/utils/commonTypes.js"; +import type { FiatProvider } from "../../../../../../pay/utils/commonTypes.js"; import { iconSize, spacing } from "../../../../../core/design-system/index.js"; import { Container } from "../../../components/basic.js"; import { Button } from "../../../components/buttons.js"; From 2dab50669b4eb4851f251a885d0d43900cc4b853 Mon Sep 17 00:00:00 2001 From: Robby Uitbeijerse Date: Thu, 22 May 2025 16:27:15 +0200 Subject: [PATCH 5/5] chore: adjust preferredProvider passed to the quote to ensure we only quote for coinbase if there isnt a preferred provider or supported provider passed down --- .../web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx index 5da2fa13403..3e6d83954e2 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx @@ -111,7 +111,7 @@ export function FiatScreenContent(props: { purchaseData: props.payOptions.purchaseData, fromAddress: payer.account.address, paymentLinkId: paymentLinkId, - preferredProvider: preferredProvider ?? "COINBASE", + preferredProvider: preferredProvider ?? supportedProviders[0], } : undefined, );