Skip to content

Commit 4e37cc8

Browse files
[SDK] feat: Redesign token selection flow in PayEmbed
1 parent 0574eac commit 4e37cc8

File tree

15 files changed

+405
-383
lines changed

15 files changed

+405
-383
lines changed

apps/playground-web/src/components/pay/direct-payment.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"use client";
2-
3-
import { sepolia } from "thirdweb/chains";
2+
import { base } from "thirdweb/chains";
43
import { PayEmbed, getDefaultToken } from "thirdweb/react";
54
import { THIRDWEB_CLIENT } from "../../lib/client";
65
import { StyledConnectButton } from "../styled-connect-button";
@@ -16,9 +15,9 @@ export function BuyMerchPreview() {
1615
payOptions={{
1716
mode: "direct_payment",
1817
paymentInfo: {
19-
amount: "0.1",
20-
chain: sepolia,
21-
token: getDefaultToken(sepolia, "USDC"),
18+
amount: "2",
19+
chain: base,
20+
token: getDefaultToken(base, "USDC"),
2221
sellerAddress: "0xEb0effdFB4dC5b3d5d3aC6ce29F3ED213E95d675",
2322
},
2423
metadata: {

apps/playground-web/src/components/pay/transaction-button.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useTheme } from "next-themes";
44
import { getContract } from "thirdweb";
5-
import { base, sepolia } from "thirdweb/chains";
5+
import { base, polygon } from "thirdweb/chains";
66
import { transfer } from "thirdweb/extensions/erc20";
77
import { claimTo, getNFT } from "thirdweb/extensions/erc1155";
88
import {
@@ -21,12 +21,12 @@ const nftContract = getContract({
2121
client: THIRDWEB_CLIENT,
2222
});
2323

24-
const USDC = getDefaultToken(sepolia, "USDC");
24+
const USDC = getDefaultToken(polygon, "USDC");
2525

2626
const usdcContract = getContract({
2727
// biome-ignore lint/style/noNonNullAssertion: its there
2828
address: USDC!.address,
29-
chain: sepolia,
29+
chain: polygon,
3030
client: THIRDWEB_CLIENT,
3131
});
3232

@@ -55,6 +55,7 @@ export function PayTransactionPreview() {
5555
to: account?.address || "",
5656
}),
5757
metadata: nft?.metadata,
58+
buyWithFiat: false,
5859
}}
5960
/>
6061
)}
@@ -69,6 +70,7 @@ export function PayTransactionButtonPreview() {
6970
return (
7071
<>
7172
<StyledConnectButton />
73+
<div className="h-10" />
7274
{account && (
7375
<div className="flex flex-col items-center justify-center gap-2">
7476
<div className="flex items-center gap-2">

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx

Lines changed: 70 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ import type { BuyWithFiatStatus } from "../../../../../../pay/buyWithFiat/getSta
88
import { formatNumber } from "../../../../../../utils/formatNumber.js";
99
import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
1010
import type { WalletId } from "../../../../../../wallets/wallet-types.js";
11-
import { useCustomTheme } from "../../../../../core/design-system/CustomThemeProvider.js";
1211
import {
1312
type Theme,
1413
fontSize,
15-
radius,
1614
spacing,
1715
} from "../../../../../core/design-system/index.js";
1816
import type {
@@ -27,10 +25,9 @@ import { LoadingScreen } from "../../../../wallets/shared/LoadingScreen.js";
2725
import type { PayEmbedConnectOptions } from "../../../PayEmbed.js";
2826
import { ChainName } from "../../../components/ChainName.js";
2927
import { Spacer } from "../../../components/Spacer.js";
30-
import { Container, ModalHeader } from "../../../components/basic.js";
28+
import { Container, Line, ModalHeader } from "../../../components/basic.js";
3129
import { Button } from "../../../components/buttons.js";
3230
import { Input } from "../../../components/formElements.js";
33-
import { Text } from "../../../components/text.js";
3431
import { TokenSymbol } from "../../../components/token/TokenSymbol.js";
3532
import { ConnectButton } from "../../ConnectButton.js";
3633
import { ChainButton, NetworkSelectorContent } from "../../NetworkSelector.js";
@@ -432,67 +429,6 @@ function BuyScreenContent(props: BuyScreenContentProps) {
432429
);
433430
}
434431

435-
if (
436-
screen.id === "select-from-token" &&
437-
supportedSourcesQuery.data &&
438-
sourceSupportedTokens
439-
) {
440-
const chains = supportedSourcesQuery.data.map((x) => x.chain);
441-
const goBack = () => setScreen(screen.backScreen);
442-
// if token selection is disabled - only show network selector screen
443-
if (
444-
payOptions.buyWithCrypto !== false &&
445-
payOptions.buyWithCrypto?.prefillSource?.allowEdits?.token === false
446-
) {
447-
return (
448-
<ChainSelectionScreen
449-
chains={chains}
450-
client={props.client}
451-
connectLocale={props.connectLocale}
452-
setChain={setFromChain}
453-
goBack={goBack}
454-
/>
455-
);
456-
}
457-
458-
return (
459-
<TokenSelectorScreen
460-
onBack={goBack}
461-
onConnect={() => {
462-
setScreen({
463-
id: "connect-payer-wallet",
464-
backScreen: screen,
465-
});
466-
}}
467-
modalTitle="Available tokens"
468-
connectLocale={props.connectLocale}
469-
client={props.client}
470-
sourceTokens={sourceSupportedTokens}
471-
sourceSupportedTokens={sourceSupportedTokens}
472-
toChain={toChain}
473-
toToken={toToken}
474-
tokenAmount={tokenAmount}
475-
fromChain={fromChain}
476-
fromToken={fromToken}
477-
mode={payOptions.mode}
478-
hiddenWallets={props.hiddenWallets}
479-
onSelect={(w, token, chain) => {
480-
const account = w.getAccount();
481-
if (account) {
482-
setPayer({
483-
account,
484-
chain,
485-
wallet: w,
486-
});
487-
setFromToken(token);
488-
setFromChain(chain);
489-
}
490-
goBack();
491-
}}
492-
/>
493-
);
494-
}
495-
496432
return (
497433
<Container animate="fadein">
498434
<div>
@@ -526,19 +462,10 @@ function BuyScreenContent(props: BuyScreenContentProps) {
526462

527463
{(screen.id === "select-payment-method" ||
528464
screen.id === "buy-with-crypto" ||
529-
screen.id === "buy-with-fiat") &&
465+
screen.id === "buy-with-fiat" ||
466+
screen.id === "select-from-token") &&
530467
payer && (
531468
<TokenSelectedLayout
532-
isBuyWithFiatEnabled={enabledPaymentMethods.buyWithFiatEnabled}
533-
isBuyWithCryptoEnabled={
534-
enabledPaymentMethods.buyWithCryptoEnabled
535-
}
536-
mode={screen.id === "buy-with-fiat" ? "buy" : "swap"}
537-
onModeChange={(mode) => {
538-
setScreen({
539-
id: mode === "swap" ? "buy-with-crypto" : "buy-with-fiat",
540-
});
541-
}}
542469
disabled={
543470
("prefillBuy" in payOptions &&
544471
payOptions.prefillBuy?.allowEdits?.amount === false) ||
@@ -551,7 +478,19 @@ function BuyScreenContent(props: BuyScreenContentProps) {
551478
setTokenAmount={setTokenAmount}
552479
client={client}
553480
onBack={() => {
554-
setScreen({ id: "main" });
481+
if (
482+
screen.id === "buy-with-crypto" ||
483+
screen.id === "buy-with-fiat"
484+
) {
485+
setScreen({
486+
id: "select-from-token",
487+
backScreen: { id: "main" },
488+
});
489+
} else if (screen.id === "select-from-token") {
490+
setScreen(screen.backScreen);
491+
} else {
492+
setScreen({ id: "main" });
493+
}
555494
}}
556495
>
557496
{screen.id === "buy-with-crypto" && activeAccount && (
@@ -614,6 +553,45 @@ function BuyScreenContent(props: BuyScreenContentProps) {
614553
setHasEditedAmount={setHasEditedAmount}
615554
/>
616555
)}
556+
557+
{screen.id === "select-from-token" &&
558+
supportedSourcesQuery.data &&
559+
sourceSupportedTokens && (
560+
<TokenSelectorScreen
561+
client={props.client}
562+
sourceTokens={sourceSupportedTokens}
563+
sourceSupportedTokens={sourceSupportedTokens}
564+
toChain={toChain}
565+
toToken={toToken}
566+
tokenAmount={tokenAmount}
567+
mode={payOptions.mode}
568+
hiddenWallets={props.hiddenWallets}
569+
onConnect={() => {
570+
setScreen({
571+
id: "connect-payer-wallet",
572+
backScreen: screen,
573+
});
574+
}}
575+
onPayWithFiat={() => {
576+
setScreen({
577+
id: "buy-with-fiat",
578+
});
579+
}}
580+
onSelectToken={(w, token, chain) => {
581+
const account = w.getAccount();
582+
if (account) {
583+
setPayer({
584+
account,
585+
chain,
586+
wallet: w,
587+
});
588+
setFromToken(token);
589+
setFromChain(chain);
590+
}
591+
setScreen({ id: "buy-with-crypto" });
592+
}}
593+
/>
594+
)}
617595
</TokenSelectedLayout>
618596
)}
619597
</div>
@@ -802,7 +780,10 @@ function MainScreen(props: {
802780
if (buyWithFiatEnabled && !buyWithCryptoEnabled) {
803781
props.setScreen({ id: "buy-with-fiat" });
804782
} else {
805-
props.setScreen({ id: "buy-with-crypto" });
783+
props.setScreen({
784+
id: "select-from-token",
785+
backScreen: { id: "main" },
786+
});
806787
}
807788
}}
808789
/>
@@ -825,7 +806,10 @@ function MainScreen(props: {
825806
if (buyWithFiatEnabled && !buyWithCryptoEnabled) {
826807
props.setScreen({ id: "buy-with-fiat" });
827808
} else {
828-
props.setScreen({ id: "buy-with-crypto" });
809+
props.setScreen({
810+
id: "select-from-token",
811+
backScreen: { id: "main" },
812+
});
829813
}
830814
}}
831815
/>
@@ -888,7 +872,10 @@ function MainScreen(props: {
888872
if (buyWithFiatEnabled && !buyWithCryptoEnabled) {
889873
props.setScreen({ id: "buy-with-fiat" });
890874
} else {
891-
props.setScreen({ id: "buy-with-crypto" });
875+
props.setScreen({
876+
id: "select-from-token",
877+
backScreen: { id: "main" },
878+
});
892879
}
893880
}}
894881
>
@@ -912,12 +899,7 @@ function TokenSelectedLayout(props: {
912899
client: ThirdwebClient;
913900
onBack: () => void;
914901
disabled?: boolean;
915-
mode: "buy" | "swap";
916-
onModeChange: (mode: "buy" | "swap") => void;
917-
isBuyWithFiatEnabled: boolean;
918-
isBuyWithCryptoEnabled: boolean;
919902
}) {
920-
const theme = useCustomTheme();
921903
return (
922904
<Container>
923905
<Container p="lg">
@@ -940,78 +922,9 @@ function TokenSelectedLayout(props: {
940922
disabled={props.disabled}
941923
/>
942924

943-
<Spacer y="lg" />
944-
<Container flex="row" gap="md" center="y">
945-
<Text size="sm"> Pay with </Text>
946-
{props.isBuyWithFiatEnabled && props.isBuyWithCryptoEnabled && (
947-
<Container
948-
flex="row"
949-
style={{
950-
flex: 1,
951-
justifyContent: "center",
952-
borderRadius: radius.xl,
953-
border: `1px solid ${theme.colors.borderColor}`,
954-
alignItems: "stretch",
955-
}}
956-
>
957-
<Button
958-
variant="ghost"
959-
style={{
960-
flex: 1,
961-
background:
962-
props.mode === "swap"
963-
? theme.colors.tertiaryBg
964-
: "transparent",
965-
borderRadius: radius.xl,
966-
borderTopRightRadius: 0,
967-
borderBottomRightRadius: 0,
968-
padding: spacing.xs,
969-
}}
970-
onClick={() => props.onModeChange("swap")}
971-
>
972-
<Text
973-
size="sm"
974-
color={
975-
props.mode === "swap" ? "primaryText" : "secondaryText"
976-
}
977-
>
978-
Crypto
979-
</Text>
980-
</Button>
981-
<div
982-
style={{
983-
width: "1px",
984-
background: theme.colors.borderColor,
985-
}}
986-
/>
987-
<Button
988-
variant="ghost"
989-
style={{
990-
flex: 1,
991-
background:
992-
props.mode === "buy"
993-
? theme.colors.tertiaryBg
994-
: "transparent",
995-
borderRadius: radius.xl,
996-
borderTopLeftRadius: 0,
997-
borderBottomLeftRadius: 0,
998-
padding: spacing.xs,
999-
}}
1000-
onClick={() => props.onModeChange("buy")}
1001-
>
1002-
<Text
1003-
size="sm"
1004-
color={props.mode === "buy" ? "primaryText" : "secondaryText"}
1005-
>
1006-
Card
1007-
</Text>
1008-
</Button>
1009-
</Container>
1010-
)}
1011-
</Container>
1012-
1013-
<Spacer y="lg" />
1014-
925+
<Spacer y="sm" />
926+
<Line />
927+
<Spacer y="sm" />
1015928
{props.children}
1016929
</Container>
1017930
</Container>

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {
3333
isNativeToken,
3434
} from "../nativeToken.js";
3535
import { useTransactionCostAndData } from "./main/useBuyTxStates.js";
36-
import { WalletRow } from "./swap/TokenSelectorScreen.js";
36+
import { WalletRow } from "./swap/WalletRow.js";
3737
import type { SupportedChainAndTokens } from "./swap/useSwapSupportedChains.js";
3838

3939
export function TransactionModeScreen(props: {

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ export function FiatScreenContent(props: {
199199
)}
200200

201201
<Container flex="column" gap="sm">
202+
<Text size="sm">Pay with</Text>
202203
<div>
203204
<PayWithCreditCard
204205
isLoading={fiatQuoteQuery.isLoading}

0 commit comments

Comments
 (0)