From 5c1e764f9d063569f08b46a15a1a7ee8a2e68667 Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Mon, 10 Jun 2024 21:55:39 +0530 Subject: [PATCH 1/6] Add currency selector --- .../thirdweb/src/pay/buyWithFiat/getQuote.ts | 2 +- .../ConnectWallet/screens/Buy/BuyScreen.tsx | 25 +++++++++++---- .../screens/Buy/PayWIthCreditCard.tsx | 8 ++--- .../screens/Buy/fiat/CurrencySelection.tsx | 32 +++++++++++++++---- .../screens/Buy/fiat/currencies.tsx | 6 ++-- .../ConnectWallet/screens/Buy/main/types.ts | 3 ++ .../screens/Buy/main/useUISelectionStates.ts | 5 ++- 7 files changed, 58 insertions(+), 23 deletions(-) diff --git a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts index 38ca915fbcd..f1869a828fd 100644 --- a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts +++ b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts @@ -34,7 +34,7 @@ export type GetBuyWithFiatQuoteParams = { * * Currently, only `USD` is supported. */ - fromCurrencySymbol: "USD"; + fromCurrencySymbol: "USD" | "CAD" | "GBP" | "EUR"; /** * The maximum slippage in basis points (bps) allowed for the transaction. 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 fd3a9ccd785..8642dcbb9b4 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 @@ -51,6 +51,7 @@ import { import { EstimatedTimeAndFees } from "./EstimatedTimeAndFees.js"; import { PayWithCreditCard } from "./PayWIthCreditCard.js"; import { PaymentSelection } from "./PaymentSelection.js"; +import { CurrencySelection } from "./fiat/CurrencySelection.js"; import { FiatFlow } from "./fiat/FiatFlow.js"; import type { CurrencyMeta } from "./fiat/currencies.js"; import type { BuyForTx, SelectedScreen } from "./main/types.js"; @@ -120,9 +121,7 @@ type BuyScreenContentProps = { isEmbed: boolean; }; -function useBuyScreenStates(options: { - payOptions: PayUIOptions; -}) { +function useBuyScreenStates(options: { payOptions: PayUIOptions }) { const { payOptions } = options; const [method, setMethod] = useState<"crypto" | "creditCard">( @@ -209,6 +208,7 @@ function BuyScreenContent(props: BuyScreenContentProps) { fromToken, setFromToken, selectedCurrency, + setSelectedCurrency, } = useUISelectionStates({ payOptions, buyForTx, @@ -271,6 +271,18 @@ function BuyScreenContent(props: BuyScreenContentProps) { return screen.node; } + if (screen.type === "select-currency") { + return ( + { + showMainScreen(); + setSelectedCurrency(currency); + }} + onBack={showMainScreen} + /> + ); + } + if (screen.type === "screen-id" && screen.name === "select-to-token") { const chains = supportedDestinations.map((x) => x.chain); // if token selection is disabled - only show network selector screen @@ -491,7 +503,9 @@ function BuyScreenContent(props: BuyScreenContentProps) { closeDrawer={closeDrawer} selectedCurrency={selectedCurrency} showCurrencySelector={() => { - // currently disabled because we are only using Stripe + setScreen({ + type: "select-currency", + }); }} account={account} /> @@ -778,7 +792,7 @@ function FiatScreenContent( const fiatQuoteQuery = useBuyWithFiatQuote( buyWithFiatOptions !== false && tokenAmount ? { - fromCurrencySymbol: "USD", // STRIPE only supports USD + fromCurrencySymbol: selectedCurrency.shorthand, toChainId: toChain.id, toAddress: account.address, toTokenAddress: isNativeToken(toToken) @@ -893,7 +907,6 @@ function FiatScreenContent( client={client} currency={selectedCurrency} onSelectCurrency={showCurrencySelector} - disableCurrencySelection={true} /> {/* Estimated time + View fees button */} void; - disableCurrencySelection?: boolean; }) { return ( {/* Left */} - + {props.currency.shorthand} - {!props.disableCurrencySelection && ( - - )} + diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/CurrencySelection.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/CurrencySelection.tsx index b319a6d9025..d292e5e6598 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/CurrencySelection.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/CurrencySelection.tsx @@ -1,4 +1,9 @@ -import { iconSize } from "../../../../../../core/design-system/index.js"; +import styled from "@emotion/styled"; +import { useCustomTheme } from "../../../../../../core/design-system/CustomThemeProvider.js"; +import { + iconSize, + spacing, +} from "../../../../../../core/design-system/index.js"; import { Spacer } from "../../../../components/Spacer.js"; import { Container, Line, ModalHeader } from "../../../../components/basic.js"; import { Button } from "../../../../components/buttons.js"; @@ -18,12 +23,12 @@ export function CurrencySelection(props: { - + {currencies.map((c) => { return ( - + ); })} @@ -42,3 +47,18 @@ export function CurrencySelection(props: { ); } + +const SelectCurrencyButton = /* @__PURE__ */ styled(Button)(() => { + const theme = useCustomTheme(); + return { + background: theme.colors.tertiaryBg, + justifyContent: "flex-start", + gap: spacing.sm, + padding: spacing.sm, + "&:hover": { + background: theme.colors.secondaryButtonBg, + transform: "scale(1.01)", + }, + transition: "background 200ms ease, transform 150ms ease", + }; +}); diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx index c867939db7d..6514add18a4 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx @@ -6,7 +6,7 @@ import { USDIcon } from "../../../icons/currencies/USDIcon.js"; import type { IconFC } from "../../../icons/types.js"; export type CurrencyMeta = { - shorthand: string; + shorthand: "USD" | "CAD" | "GBP" | "EUR"; name: string; icon: IconFC; }; @@ -17,7 +17,7 @@ export const defaultSelectedCurrency: CurrencyMeta = { icon: USDIcon, }; -export const currencies = [ +export const currencies: CurrencyMeta[] = [ defaultSelectedCurrency, { shorthand: "CAD", @@ -45,7 +45,7 @@ export function getCurrencyMeta(shorthand: string): CurrencyMeta { // This should never happen icon: UnknownCurrencyIcon, name: shorthand, - shorthand, + shorthand: shorthand as CurrencyMeta["shorthand"], } ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/types.ts b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/types.ts index bff52b7688e..5f11a854bfd 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/types.ts +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/types.ts @@ -18,4 +18,7 @@ export type SelectedScreen = } | { type: "main"; + } + | { + type: "select-currency"; }; diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts index 69c1ad14dd6..c4a6398d3e3 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts @@ -74,7 +74,9 @@ export function useUISelectionStates(options: { // -------------------------------------------------------------------------- // stripe only supports USD, so not using a state right now - const selectedCurrency = defaultSelectedCurrency; + const [selectedCurrency, setSelectedCurrency] = useState( + defaultSelectedCurrency, + ); return { tokenAmount, @@ -91,5 +93,6 @@ export function useUISelectionStates(options: { setFromToken, selectedCurrency, setHasEditedAmount, + setSelectedCurrency, }; } From fe38464d43c242e8bb0cafa74ee2e3e9eaec2ce5 Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Mon, 10 Jun 2024 21:58:23 +0530 Subject: [PATCH 2/6] patch changeset --- .changeset/twelve-hornets-cough.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twelve-hornets-cough.md diff --git a/.changeset/twelve-hornets-cough.md b/.changeset/twelve-hornets-cough.md new file mode 100644 index 00000000000..823393ed72d --- /dev/null +++ b/.changeset/twelve-hornets-cough.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Allow selecting fiat currency in Pay UI From 4ddf0c3c8869ee6a4c49478a38489f53bfc6f9d8 Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Mon, 10 Jun 2024 22:03:22 +0530 Subject: [PATCH 3/6] Update FiatTxDetialsTable --- .../ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx index 059f9303adf..ac9383ad924 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatTxDetailsTable.tsx @@ -11,9 +11,9 @@ import { Spacer } from "../../../../components/Spacer.js"; import { Container, Line } from "../../../../components/basic.js"; import { ButtonLink } from "../../../../components/buttons.js"; import { Text } from "../../../../components/text.js"; -import { USDIcon } from "../../../icons/currencies/USDIcon.js"; import { TokenInfoRow } from "../tx-history/TokenInfoRow.js"; import type { FiatStatusMeta } from "../tx-history/statusMeta.js"; +import { getCurrencyMeta } from "./currencies.js"; /** * Show a table with the details of a "OnRamp" transaction step in the "Buy with Fiat" flow. @@ -40,6 +40,7 @@ export function OnRampTxDetailsTable(props: { }) { const onRampChainQuery = useChainQuery(getCachedChain(props.token.chainId)); const onrampTxHash = props.statusMeta?.txHash; + const currencyMeta = getCurrencyMeta(props.fiat.currencySymbol); const lineSpacer = ( <> @@ -79,9 +80,7 @@ export function OnRampTxDetailsTable(props: { }} > - {props.fiat.currencySymbol === "USD" && ( - - )} + {formatNumber(Number(props.fiat.amount), 4)}{" "} {props.fiat.currencySymbol} From 975006d4ffc21ebc637f59efb04a9496dab5c214 Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Tue, 11 Jun 2024 00:47:07 +0530 Subject: [PATCH 4/6] Update jsdoc comment --- packages/thirdweb/src/pay/buyWithFiat/getQuote.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts index f1869a828fd..3b4ac0e9eae 100644 --- a/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts +++ b/packages/thirdweb/src/pay/buyWithFiat/getQuote.ts @@ -31,8 +31,6 @@ export type GetBuyWithFiatQuoteParams = { /** * Symbol of the fiat currency to buy the token with. - * - * Currently, only `USD` is supported. */ fromCurrencySymbol: "USD" | "CAD" | "GBP" | "EUR"; From 7f041fa335e163bda103ea3aaad0e504f025e44c Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Tue, 11 Jun 2024 00:51:30 +0530 Subject: [PATCH 5/6] Fix tokenIcon --- packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx b/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx index e19d6d57b6a..771d3c44ab3 100644 --- a/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx +++ b/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx @@ -10,6 +10,7 @@ import { isNativeToken, } from "../ConnectWallet/screens/nativeToken.js"; import { Img } from "./Img.js"; +import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; // Note: Must not use useConnectUI here @@ -30,7 +31,7 @@ export function TokenIcon(props: { const chainQuery = useChainQuery(props.chain); const tokenImage = useMemo(() => { - if (isNativeToken(props.token)) { + if (isNativeToken(props.token) || props.token.address === NATIVE_TOKEN_ADDRESS) { return chainQuery.data?.icon?.url; } return props.token.icon; From 8848a9bd15ad7b0e8096ced72c27d71976eb6572 Mon Sep 17 00:00:00 2001 From: Manan Tank Date: Tue, 11 Jun 2024 04:23:12 +0530 Subject: [PATCH 6/6] Fix lint --- .../thirdweb/src/react/web/ui/components/TokenIcon.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx b/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx index 771d3c44ab3..994d2e43739 100644 --- a/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx +++ b/packages/thirdweb/src/react/web/ui/components/TokenIcon.tsx @@ -2,6 +2,7 @@ import { useMemo } from "react"; import type { Chain } from "../../../../chains/types.js"; import type { ThirdwebClient } from "../../../../client/client.js"; +import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; import { iconSize } from "../../../core/design-system/index.js"; import { useChainQuery } from "../../../core/hooks/others/useChainQuery.js"; import { genericTokenIcon } from "../ConnectWallet/icons/dataUris.js"; @@ -10,7 +11,6 @@ import { isNativeToken, } from "../ConnectWallet/screens/nativeToken.js"; import { Img } from "./Img.js"; -import { NATIVE_TOKEN_ADDRESS } from "../../../../constants/addresses.js"; // Note: Must not use useConnectUI here @@ -31,7 +31,10 @@ export function TokenIcon(props: { const chainQuery = useChainQuery(props.chain); const tokenImage = useMemo(() => { - if (isNativeToken(props.token) || props.token.address === NATIVE_TOKEN_ADDRESS) { + if ( + isNativeToken(props.token) || + props.token.address === NATIVE_TOKEN_ADDRESS + ) { return chainQuery.data?.icon?.url; } return props.token.icon;