diff --git a/.changeset/silent-comics-carry.md b/.changeset/silent-comics-carry.md
new file mode 100644
index 00000000000..0b101c7e75f
--- /dev/null
+++ b/.changeset/silent-comics-carry.md
@@ -0,0 +1,5 @@
+---
+"thirdweb": patch
+---
+
+Add fiat provider selection in PayEmbed
diff --git a/apps/playground-web/src/components/pay/embed.tsx b/apps/playground-web/src/components/pay/embed.tsx
index a67bd47f6bc..2b073042326 100644
--- a/apps/playground-web/src/components/pay/embed.tsx
+++ b/apps/playground-web/src/components/pay/embed.tsx
@@ -10,7 +10,7 @@ export function StyledPayEmbedPreview() {
const { theme } = useTheme();
return (
- <>
+
);
}
diff --git a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts
index 015e0dcaab9..bb9a0bb09b7 100644
--- a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts
+++ b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts
@@ -238,6 +238,11 @@ export type BuyWithFiatQuote = {
*
*/
onRampLink: string;
+
+ /**
+ * The provider that was used to get the quote.
+ */
+ provider: FiatProvider;
};
/**
diff --git a/packages/thirdweb/src/pay/utils/commonTypes.ts b/packages/thirdweb/src/pay/utils/commonTypes.ts
index ad6f80cdc2f..bd34ff2f534 100644
--- a/packages/thirdweb/src/pay/utils/commonTypes.ts
+++ b/packages/thirdweb/src/pay/utils/commonTypes.ts
@@ -17,4 +17,6 @@ export type PayOnChainTransactionDetails = {
explorerLink?: string;
};
-export type FiatProvider = "STRIPE" | "TRANSAK" | "KADO" | "COINBASE";
+export type FiatProvider = (typeof FiatProviders)[number];
+
+export const FiatProviders = ["COINBASE", "STRIPE", "TRANSAK", "KADO"] as const;
diff --git a/packages/thirdweb/src/react/core/utils/storage.ts b/packages/thirdweb/src/react/core/utils/storage.ts
index c6bb7bb0d6b..0472b369528 100644
--- a/packages/thirdweb/src/react/core/utils/storage.ts
+++ b/packages/thirdweb/src/react/core/utils/storage.ts
@@ -2,6 +2,7 @@ import type { AsyncStorage } from "../../../utils/storage/AsyncStorage.js";
import type { AuthArgsType } from "../../../wallets/in-app/core/authentication/types.js";
export const LAST_AUTH_PROVIDER_STORAGE_KEY = "lastAuthProvider";
+export const PREFERRED_FIAT_PROVIDER_STORAGE_KEY = "preferredFiatProvider";
export async function setLastAuthProvider(
authProvider: AuthArgsType["strategy"],
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx
index 3ac5f3246ef..2e7c868af16 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx
@@ -1,3 +1,4 @@
+import { ChevronDownIcon } from "@radix-ui/react-icons";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useCallback, useMemo, useState } from "react";
import type { Chain } from "../../../../../../chains/types.js";
@@ -10,11 +11,13 @@ import type { GetBuyWithCryptoQuoteParams } from "../../../../../../pay/buyWithC
import type { BuyWithCryptoStatus } from "../../../../../../pay/buyWithCrypto/getStatus.js";
import type { BuyWithFiatStatus } from "../../../../../../pay/buyWithFiat/getStatus.js";
import { isSwapRequiredPostOnramp } from "../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
+import type { FiatProvider } from "../../../../../../pay/utils/commonTypes.js";
import { formatNumber } from "../../../../../../utils/formatNumber.js";
import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
import type { WalletId } from "../../../../../../wallets/wallet-types.js";
import {
type Theme,
+ iconSize,
spacing,
} from "../../../../../core/design-system/index.js";
import type {
@@ -27,6 +30,7 @@ import { useBuyWithFiatQuote } from "../../../../../core/hooks/pay/useBuyWithFia
import { useActiveAccount } from "../../../../../core/hooks/wallets/useActiveAccount.js";
import { invalidateWalletBalance } from "../../../../../core/providers/invalidateWalletBalance.js";
import type { SupportedTokens } from "../../../../../core/utils/defaultTokens.js";
+import { PREFERRED_FIAT_PROVIDER_STORAGE_KEY } from "../../../../../core/utils/storage.js";
import { ErrorState } from "../../../../wallets/shared/ErrorState.js";
import { LoadingScreen } from "../../../../wallets/shared/LoadingScreen.js";
import type { PayEmbedConnectOptions } from "../../../PayEmbed.js";
@@ -56,6 +60,7 @@ import { PayWithCreditCard } from "./PayWIthCreditCard.js";
import { TransactionModeScreen } from "./TransactionModeScreen.js";
import { CurrencySelection } from "./fiat/CurrencySelection.js";
import { FiatFlow } from "./fiat/FiatFlow.js";
+import { Providers } from "./fiat/Providers.js";
import type { CurrencyMeta } from "./fiat/currencies.js";
import type { SelectedScreen } from "./main/types.js";
import {
@@ -1255,9 +1260,22 @@ function FiatScreenContent(props: {
const receiverAddress =
defaultRecipientAddress || props.payer.account.address;
const { drawerRef, drawerOverlayRef, isOpen, setIsOpen } = useDrawer();
- const [drawerScreen, setDrawerScreen] = useState<"fees">("fees");
+ const [drawerScreen, setDrawerScreen] = useState<"fees" | "providers">(
+ "fees",
+ );
const buyWithFiatOptions = props.payOptions.buyWithFiat;
+ const [preferredProvider, setPreferredProvider] = useState<
+ FiatProvider | undefined
+ >(
+ buyWithFiatOptions !== false
+ ? buyWithFiatOptions?.preferredProvider ||
+ ((localStorage.getItem(
+ PREFERRED_FIAT_PROVIDER_STORAGE_KEY,
+ ) as FiatProvider | null) ??
+ undefined)
+ : undefined,
+ );
const fiatQuoteQuery = useBuyWithFiatQuote(
buyWithFiatOptions !== false && tokenAmount
@@ -1273,7 +1291,7 @@ function FiatScreenContent(props: {
isTestMode: buyWithFiatOptions?.testMode,
purchaseData: props.payOptions.purchaseData,
fromAddress: payer.account.address,
- preferredProvider: buyWithFiatOptions?.preferredProvider,
+ preferredProvider: preferredProvider,
}
: undefined,
);
@@ -1314,6 +1332,11 @@ function FiatScreenContent(props: {
setIsOpen(true);
}
+ function showProviders() {
+ setDrawerScreen("providers");
+ setIsOpen(true);
+ }
+
const disableSubmit = !fiatQuoteQuery.data;
const errorMsg =
@@ -1337,6 +1360,28 @@ function FiatScreenContent(props: {
)}
+ {drawerScreen === "providers" && (
+
+
+ Providers
+
+
+
{
+ setPreferredProvider(provider);
+ // save the pref in local storage
+ localStorage.setItem(
+ PREFERRED_FIAT_PROVIDER_STORAGE_KEY,
+ provider,
+ );
+ setIsOpen(false);
+ }}
+ />
+
+ )}
>
)}
@@ -1349,6 +1394,35 @@ function FiatScreenContent(props: {
currency={selectedCurrency}
onSelectCurrency={showCurrencySelector}
/>
+
+
+ Provider
+
+
+
{/* Estimated time + View fees button */}
void;
+}) {
+ return (
+
+ {FiatProviders.map((provider) => {
+ return (
+
+
+
+ );
+ })}
+
+ );
+}